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.
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()
To fix the IndexError replace lines 156-157 with:
A index was needed for insert too - That should make the scores sorted well from lowest to highest.