Welcome, guest | Sign In | My Account | Store | Cart

As the final version of the War Game, development finally came to a halt as the prototype exceeded it bounds for design. Yes, you can write your program as one large function, but should you? This recipe demonstrates that program without proper style can lead to a mess very quickly. Practice good coding standards, or you can easily loose focus and the ability to maintain your code.

Python, 175 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
from random import randint, seed
from time import time
# region: change
# from window import *
from Zpaw import *
from cards import *
card_list = [card_0, card_1, card_2, card_3, card_4, card_5, card_6, card_7, card_8, card_9]
# endregion

# page & window dimensions have been corrected.
def game():
    print 'Welcome to WAR V6!'
    print
    asking = True
    while asking:
        try:
            players = int(raw_input('How many players are there? '))
            if players < 2:
                print 'There must be at least two players.'
            else:
                asking = False
        except:
            print 'You must enter a number.'
    print
    names = []
    # region: change
    longest_name = 0
    for name in range(players):
        names.append(raw_input('What is the name of player ' + str(name + 1) + '? '))
        if len(names[-1]) > longest_name:
            longest_name = len(names[-1])
    # endregion
    deck = []
    for card in range(10):
        for player in range(players):
            deck.append(card)
    hands = []
    seed(time())
    for player in range(players):
        hand = ([], [])
        for card in range(10):
            index = randint(0, len(deck) - 1)
            hand[0].append(deck[index])
            del deck[index]
        hand[0].sort()
        hands.append(hand)
    for round in range(1, 11):
        table = []
        will_play = []
        high_card = 0
        for player in range(players):
            will_play.append(player)
        for turn in range(players):
            for line in range(50):
                print
            index = randint(0, len(will_play) - 1)
            now_play = will_play[index]
            del will_play[index]
            print 'Round', round
            raw_input('It is ' + names[now_play] + "'s turn to play.")
            print
            # region: change
            if len(table) == 0:
                print 'There are no cards on the table.\n'
            else:
                table_window = window(longest_name + 13, len(table) * 6)
                for card in range(len(table)):
                    # name_page = page(1, len(names[table[card][0]]) + 9)
                    # name_page.mutate(0, 0, names[table[card][0]] + ' played')
                    # table_window.append(name_page, [card * 6, 0])
                    # table_window.append(card_list[table[card][1]], [card * 6, len(names[table[card][0]]) + 8])
                    # table_window += struct(True, card * 6, 0, name_page)
                    # table_window += struct(True, card * 6, len(names[table[card][0]]) + 8, card_list[table[card][1]])
                    table_window += page(len(names[table[card][0]]) + 9, 1) \
                                    .mutate(0, 0, names[table[card][0]] + ' played').y(card * 6)
                    table_window += page(0, 0).link(card_list[table[card][1]]) \
                                    .x(len(names[table[card][0]]) + 8).y(card * 6)
                print table_window
            print 'These are your playing cards:'
            playing_window = window(len(hands[now_play][0]) * 6, 7)
            for index in range(len(hands[now_play][0])):
                # playing_window.append(card_list[hands[now_play][0][index]], [1, index * 6 + 1])
                # playing_window += struct(True, 1, index * 6 + 1, card_list[hands[now_play][0][index]])
                playing_window += page(0, 0).link(card_list[hands[now_play][0][index]]).x(index * 6 + 1).y(1)
            print playing_window
            if len(hands[now_play][1]) > 0:
                hands[now_play][1].sort()
                print 'These are your captured cards:'
                capture_window = window(len(hands[now_play][1]) * 6, 7)
                for index in range(len(hands[now_play][1])):
                    # capture_window.append(card_list[hands[now_play][1][index]], [1, index * 6 + 1])
                    # capture_window += struct(True, 1, index * 6 + 1, card_list[hands[now_play][1][index]])
                    capture_window += page(0, 0).link(card_list[hands[now_play][1][index]]).x(index * 6 + 1).y(1)
                print capture_window
            # endregion
            asking = True
            while asking:
                try:
                    card = int(raw_input('What card do you want to play? '))
                    if card >= 0 and card <= 9:
                        try:
                            hands[now_play][0].remove(card)
                            table.append((now_play, card))
                            if card > high_card:
                                high_card = card
                            asking = False
                        except:
                            print 'You do not have that card.'
                    else:
                        print 'You must enter a value between -1 and 10.'
                except:
                    print 'You must enter a number.'
        for line in range(50):
            print
        #region: change
        table_window = window(longest_name + 13, len(table) * 6)
        for card in range(len(table)):
            # name_page = page(1, len(names[table[card][0]]) + 9)
            # name_page.mutate(0, 0, names[table[card][0]] + ' played')
            # table_window.append(name_page, [card * 6, 0])
            # table_window.append(card_list[table[card][1]], [card * 6, len(names[table[card][0]]) + 8])
            # table_window += struct(True, card * 6, 0, name_page)
            # table_window += struct(True, card * 6, len(names[table[card][0]]) + 8, card_list[table[card][1]])
            table_window += page(len(names[table[card][0]]) + 9, 1) \
                            .mutate(0, 0, names[table[card][0]] + ' played').y(card * 6)
            table_window += page(0, 0).link(card_list[table[card][1]]) \
                            .x(len(names[table[card][0]]) + 8).y(card * 6)
        print table_window
        # endregion
        hand_out = []
        for index in range(players):
            if table[index][1] == high_card:
                hand_out.append(table[index][0])
        while len(table) > 0:
            hands[hand_out[randint(0, len(hand_out) - 1)]][1].append(table[0][1])
            del table[0]
        for player in range(players):
            if len(hands[player][1]) > 0:
                   print names[player] + ' has captured ' + str(len(hands[player][1])) + ' cards.'
        print
        raw_input('End Of Round ' + str(round))
    for line in range(50):
        print
    high_score = 0
    scores = []
    for player in range(players):
        total = 0
        for card in range(len(hands[player][1])):
            total += hands[player][1][card]
        if total > high_score:
            high_score = total
        if len(scores) == 0 or scores[len(scores) - 1][1] <= total:
            scores.append((player, total))
        else:
            for index in range(len(scores)):
                if total > scores[index][1]:
                    scores.insert((player, total))
                    break
    try:
        for player in range(players):
            # Next line of code has a problem (IndexError).
            print names[scores[player][0]] + ' received ' + str(scores[player][1]) + ' points.'
        print
        for index in range(10):
            raw_input('GAME OVER ... ' + str(9 - index))
    except Exception, bug:
        print
        print 'Oops!'
        print '\t', bug
        raw_input()

# NOTE:
# Am considering re-writing this game.
if __name__ == '__main__':
    game()

You will need the following files to run the program listed up above.

cards.py

import Zpaw

# Card definitions are simpler that before.
card_0
= Zpaw.page(5, 5).mutate(0, 0, '+---+').mutate(1, 0, '|   |').mutate(2, 0, '| 0 |').mutate(3, 0, '|   |').mutate(4, 0, '+---+')
card_1
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 2, '1')
card_2
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 2, '2')
card_3
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 2, '3')
card_4
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 2, '4')
card_5
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 2, '5')
card_6
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 2, '6')
card_7
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 2, '7')
card_8
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 2, '8')
card_9
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 2, '9')
card_10
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 1, '1 0')
card_A
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 2, 'A')
card_J
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 2, 'J')
card_Q
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 2, 'Q')
card_K
= Zpaw.page(0, 0).link(card_0).unlink().mutate(2, 2, 'K')

# Test what the cards look like.
def main():
   
print card_0
   
print card_1
   
print card_2
   
print card_3
   
print card_4
   
print card_5
   
print card_6
   
print card_7
   
print card_8
   
print card_9
   
print card_10
   
print card_A
   
print card_J
   
print card_Q
   
print card_K

# Test this module.
if __name__ == '__main__':
    main
()

Zam.py

# Name & Description
# ==================

'''Support module for array and matrix use.

This module provides two classes that emulate one and two
dimentional lists with fixed sizes but mutable internals.'''


# Data & Imports
# ==============

__all__
= ['array', 'matrix']
__version__
= '1.1'

import sys

# Public Names
# ============

class array(object):

   
'''array(length) -> new array
    array(length, value) -> initialized from value'''


   
def __init__(self, length, value=None):
       
'''x.__init__(...) initializes x'''
       
self.__data = range(length)
       
for index in range(length):
           
self.__data[index] = value

   
def __repr__(self):
       
'''x.__repr__() <==> repr(x)'''
       
return repr(self.__data)

   
def __len__(self):
       
'''x.__len__() <==> len(x)'''
       
return len(self.__data)

   
def __getitem__(self, key):
       
'''x.__getitem__(y) <==> x[y]'''
       
return self.__data[key]

   
def __setitem__(self, key, value):
       
'''x.__setitem__(i, y) <==> x[i]=y'''
       
self.__data[key] = value

   
def __delitem__(self, key):
       
'''x.__delitem__(y) <==> del x[y]'''
       
self.__data[key] = None

   
def __iter__(self):
       
'''x.__iter__() <==> iter(x)'''
       
return iter(self.__data)

   
def __contains__(self, value):
       
'''x.__contains__(y) <==> y in x'''
       
return value in self.__data

class matrix(object):

   
'''matrix(rows, columns) -> new matrix
    matrix(rows, columns, value) -> initialized from value'''


   
def __init__(self, rows, columns, value=None):
       
'''x.__init__(...) initializes x'''
       
self.__data = array(rows)
       
for index in range(rows):
           
self.__data[index] = array(columns, value)

   
def __repr__(self):
       
'''x.__repr__() <==> repr(x)'''
       
return repr(self.__data)

   
def __len__(self):
       
'''x.__len__() <==> len(x)'''
       
return len(self.__data)

   
def __getitem__(self, key):
       
'''x.__getitem__(y) <==> x[y]'''
       
return self.__data[key]

   
def __setitem__(self, key, value):
       
'''x.__setitem__(i, y) <==> x[i]=y'''
       
self.__data[key] = array(len(self.__data[key]), value)

   
def __delitem__(self, key):
       
'''x.__delitem__(y) <==> del x[y]'''
       
self.__data[key] = array(len(self.__data[key]))

   
def __iter__(self):
       
'''x.__iter__() <==> iter(x)'''
       
return iter(self.__data)

   
def __contains__(self, value):
       
'''x.__contains__(y) <==> y in x'''
       
for item in self.__data:
           
if value in item:
               
return True
       
return False

# Private Names
# =============

def main():
   
print 'Content-Type: text/plain'
   
print
   
print file(sys.argv[0]).read()

# Execute Main
# ============

if __name__ == '__main__':
    main
()

Zpaw.py

import Zam

class ClassError(StandardError): # VERSION 1.0
   
pass # This class is just for exceptions.

class page(object): # VERSION 1.3

   
def __init__(self, width, height, value=None):
       
self.__assert_type((int, height), (int, width))
       
if value is None:
            value
= ''
       
else:
           
self.__assert_type((str, value))
       
if value:
           
self.__data = Zam.matrix(height, width, value[0])
       
else:
           
self.__data = Zam.matrix(height, width, ' ')
       
self.__visible = True
       
self.__x = 0
       
self.__y = 0

   
def __repr__(self):
       
return repr(self.__data)

   
def __str__(self):
       
return '\n'.join([''.join(row) for row in self.__data])

   
def width(self):
       
return len(self.__data[0])

   
def height(self):
       
return len(self.__data)

   
def access(self, row, column, length=None):
       
self.__assert_type((int, row), (int, column))
       
if length is None:
            length
= 1
       
else:
           
self.__assert_type((int, length))
       
string = str()
       
for index in range(length):
           
try:
               
string += self.__data[row][column + index]
           
except:
               
pass
       
return string

   
def mutate(self, row, column, value):
       
self.__assert_type((int, row), (int, column), (str, value))
       
for index in range(len(value)):
           
try:
               
self.__data[row][column + index] = value[index]
           
except:
               
pass
       
return self

   
def set_row(self, row, value=None):
       
self.__assert_type((int, row))
       
if value is None:
            value
= ''
       
else:
           
self.__assert_type((str, value))
       
if value:
           
self.__data[row] = value[0]
       
else:
           
self.__data[row] = ' '
       
return self

   
def set_column(self, column, value=None):
       
self.__assert_type((int, column))
       
if value is None:
            value
= ''
       
else:
           
self.__assert_type((str, value))
       
for row in self.__data:
           
if value:
                row
[column] = value[0]
           
else:
                row
[column] = ' '
       
return self

   
def visible(self, value=None):
       
if value is None:
           
return self.__visible
       
else:
           
self.__assert_type((bool, value))
           
self.__visible = value
           
return self

   
def x(self, value=None):
       
if value is None:
           
return self.__x
       
else:
           
self.__assert_type((int, value))
           
self.__x = value
           
return self

   
def y(self, value=None):
       
if value is None:
           
return self.__y
       
else:
           
self.__assert_type((int, value))
           
self.__y = value
           
return self

   
def page(self, ids=None): # ids=None is for recursion bug fix.
       
return self

   
def _page(self): # This functions is for recursion bug fix.
       
return self

   
def project(self, value): # Does not respect value.visible().
       
self.__assert_class((page, value))
       
for row in range(value.height()):
           
for column in range(value.width()):
               
try:
                   
self.__data \
                               
[row + value.y()] \
                               
[column + value.x()] = \
                                value
.__data[row][column]
               
except:
                   
pass
       
return self

   
def link(self, value): # Loses current matrix and uses value's.
       
self.__assert_class((page, value))
       
self.__data = value.__data
       
return self

   
def unlink(self): # Copies and unlinks current matrix.
        temp
= Zam.matrix(self.height(), self.width())
       
for row in range(self.height()):
           
for column in range(self.width()):
                temp
[row][column] = self.__data[row][column]
       
self.__data = temp
       
return self

   
def __assert_class(self, *tuples):
       
for classes, objects in tuples:
           
if objects.__class__ is not classes:
               
raise ClassError(str(objects.__class__) + ' is not ' + str(classes))

   
def __assert_type(self, *tuples):
       
for types, objects in tuples:
           
if type(objects) is not types:
               
raise TypeError

class window(object): # VERSION 1.7

   
def __init__(self, width, height, border=None, background=None):
       
self.__assert_type((int, width), (int, height))
       
if border is None:
            border
= ''
       
else:
           
self.__assert_type((str, border))
       
if background is None:
            background
= ''
       
else:
           
self.__assert_type((str, background))
       
self.__width = width
       
self.__height = height
       
if border:
           
self.__border = border[0]
       
else:
           
self.__border = None
       
if background:
           
self.__background = background[0]
       
else:
           
self.__background = ' '
       
self.__list = list()
       
# __page must exist for __refresh.
       
self.__page = page(0, 0)
       
self.__refresh()


   
def __repr__(self):
       
self.__refresh()
       
return repr(self.__page)

   
def __str__(self):
       
self.__refresh()
       
return str(self.__page)

   
def width(self, value=None):
       
if value is None:
           
return self.__width
       
else:
           
self.__assert_type((int, value))
           
self.__width = value
           
return self

   
def height(self, value=None):
       
if value is None:
           
return self.__height
       
else:
           
self.__assert_type((int, value))
           
self.__height = value
           
return self

   
def border(self, value=None):
       
if value is None:
           
return self.__border
       
else:
           
self.__assert_type((str, value))
           
if value:
               
self.__border = value[0]
           
else:
               
self.__border = None
           
return self

   
def background(self, value=None):
       
if value is None:
           
return self.__background
       
else:
           
self.__assert_type((str, value))
           
if value:
               
self.__background = value[0]
           
else:
               
self.__background = ' '
           
return self

   
def __len__(self):
       
return len(self.__list)

   
def __getitem__(self, key):
       
self.__assert_type((int, key))
       
return self.__list[key]

   
def __setitem__(self, key, value):
       
self.__assert_type((int, key))
       
self.__assert_class((page, window, value))
       
self.__list[key] = value

   
def __delitem__(self, key):
       
self.__assert_type((int, key))
       
del self.__list[key]

   
def __iter__(self):
       
return iter(self.__list)

   
def __contains__(self, value):
       
self.__assert_class((page, window, value))
       
return value in self.__list

   
def __iadd__(self, value):
       
self.__assert_class((page, window, value))
       
self.__list.append(value)
       
return self # Must return self.

   
def __isub__(self, value):
       
self.__assert_class((page, window, value))
       
while value in self.__list:
           
self.__list.remove(value)
       
return self # Must return self.

   
def visible(self, value=None):
       
if value is None:
           
return self.__page.visible()
       
else:
           
# Check type here and return self.
           
self.__assert_type((bool, value))
           
self.__page.visible(value)
           
return self

   
def x(self, value=None):
       
if value is None:
           
return self.__page.x()
       
else:
           
# Check type here and return self.
           
self.__assert_type((int, value))
           
self.__page.x(value)
           
return self

   
def y(self, value=None):
       
if value is None:
           
return self.__page.y()
       
else:
           
# Check type here and return self.
           
self.__assert_type((int, value))
           
self.__page.y(value)
           
return self

   
def page(self, ids=None):
       
# ids=None helps prevent too much recursion.
       
if ids is not None:
           
self.__assert_type((list, ids))
       
self.__refresh(ids)
       
return self.__page

   
def _page(self): # Don't refresh __page.
       
return self.__page

   
def __refresh(self, ids=None):
       
if ids is None:
            ids
= list()
       
# region: should not be executed if id(self) in ids.
        temp
= page(self.__width, self.__height, self.__background) \
               
.visible(self.__page.visible()).x(self.__page.x()).y(self.__page.y())
       
self.__page = temp
       
for item in self.__list:
           
if item.visible():
               
# This needs to be fixed.
               
if id(item) in ids:
                   
self.__page.project(item._page())
               
else:
                    ids
.append(id(item))
                   
self.__page.project(item.page(ids))
       
# endregion
       
# The border still needs to finished.
       
# Border needs be finished for caller and projection.
       
if self.__border:
           
self.__page \
                       
.set_row(0, self.__border).set_row(self.__height - 1, self.__border) \
                       
.set_column(0, self.__border).set_column(self.__width - 1, self.__border)

   
def __assert_class(self, *tuples):
       
# This function allows checking against several classes.
       
# Note: self.__assert_class((class, ..., object), ...)
       
for objects in tuples:
           
for classes in objects[:-1]:
               
if objects[-1].__class__ is classes:
                   
break
           
if objects[-1].__class__ is not classes:
               
raise ClassError

   
def __assert_type(self, *tuples):
       
# Allows checking against only one type per object.
       
# Note: self.__assert_type((type, object), ...)
       
for types, objects in tuples:
           
if type(objects) is not types:
               
raise TypeError

# TEST CODE

def main():
   
# PART 1
   
print 'PART 1'
    it
= window(10, 10)
   
print it
   
print it.border('#')
   
print it.background('-')
    it
+= page(1, 1, '%').x(2).y(2)
   
print it
    other
= page(2, 2, 'H')
    it
+= other.x(3).y(3)
   
print it
    it
-= other
   
print it
   
del it[0]
   
print it
    other
= page(2, 2, '%')
    it
+= other.x(2).y(2)
   
print it
    other_2
= page(0, 0)
    it
+= other_2.y(5).x(2).link(other)
   
print it
    other_2
.mutate(0, 0, 'H')
   
print it
   
print it.border('').background('')
   
# PART 2
   
print 'PART 2'
    test
= window(40, 20, '#', '.')
   
print test
    copy
= page(0, 0).link(test.page())
    test
+= page(5, 5).mutate(0, 0, '+---+').mutate(1, 0, '|   |')
   
print test
    test
+= page(0, 0).link(test[0].x(3).y(2)).x(3).y(11)
   
print test
    test
[1].mutate(2, 0, '| A |').mutate(3, 0, test[0].access(1, 0, 5))
   
print test
    test
[0].mutate(4, 0, test[1].access(0, 0, 5))
   
print test
    test
[0].visible(False)
   
print test
    test
[0].mutate(2, 2, 'B')
   
print test
    test
[0].visible(True)
    test
[1].visible(False)
   
print test
    test
.height(10).width(20)[1] =  page(3, 3, 'X').x(6).y(5)
   
print test
   
print copy
   
# PART 3 - recursion depth fix
   
print 'PART 3'
   
try:
        test
+= test
       
print test
       
print test.x(5).y(5)
       
# NOTE: border cannot be shown with recusion
   
except RuntimeError, bug:
       
print 'TEST FAILED:', bug

if __name__ == '__main__':
    main
()

1 comment

Yoni Messica 11 years, 3 months ago  # | flag

To fix the IndexError replace lines 156-157 with:

            if total < scores[index][1]:
                scores
.insert(index, (player, total))

A index was needed for insert too - That should make the scores sorted well from lowest to highest.