#python #c #curses #conways-game-of-life
#python #c #проклятия #конвей-игра жизни
Вопрос:
У меня единственная ошибка вне диапазона при попытке выполнить итерацию по сетке для подсчета соседних ячеек. Это почти сделано, но я уже потратил пару часов на эту ошибку. Я полон решимости разобраться с остальными из них, если таковые будут, после этого. лол. Я никогда раньше не обращался за помощью по stack exchange, поэтому будьте уверены, что я бы не стал, если бы не перепробовал все и не был полностью разочарован. Полегче со мной. лол
Код на C работает. Если кому-нибудь нужны объявления для реализации на C, я был бы рад их опубликовать.
Чтобы воспроизвести ошибку, запустите ее с помощью python3 в терминале * nix и нажмите «enter». Вы могли бы сделать это в Windows, но я думаю, вам нужно немного поработать с pdcurses.
Теперь кажется возможным, что в коде C есть необнаруженные ошибки, несмотря на то, что он работает и не выдает предупреждений компилятора.
Предполагается, что при выполнении итерации по 2D-массиву код должен работать путем добавления 1 к индексу сетки (grid.cell), чтобы не выходить за границы при подсчете ячеек непосредственно за пределами экрана. Из элементарного вывода отладки, который я добавил в grid.neighbour_count, я вижу, что он проходит весь путь до дальней стороны экрана по оси x, прежде чем выдает ошибку, поэтому отрицательное значение по оси y, похоже, работает так, как ожидалось. Я видел несколько других способов сделать это, но этот мне кажется самым элегантным, и он уже работает на C.
Сообщение об ошибке
Traceback (most recent call last):
File "./life.py", line 118, in <module>
main()
File "./life.py", line 100, in main
grid.draw_next(term)
File "./life.py", line 49, in draw_next
j = self.neighbor_count(y,x)
File "./life.py", line 38, in neighbor_count
count = self.cell[i 1][j 1]
IndexError: list index out of range
Python
from blessed import Terminal
#import signal
import sys
def echo(text):
print(text, end='', flush=True)
class Grid(object):
def __init__(self, y, x):
self.cell = [([0] * x) for i in range(y)]
def resize(self, y, x):
pass
def width(self, x=0):
if not x: return len(self.cell[0][:])
def height(self, y=0):
if not y: return len(self.cell[:][:])
def toggle_cell(self, y, x):
i = self.cell[y][x]
if i:
self.cell[y][x] = 0
return 0
else:
self.cell[y][x] = 1
return 1
def neighbor_count(self, y, x):
count = 0
for i in range(y-1,y 2):
for j in range(x-1,x 2):
# debug sys.stderr.write('i: {0} j: {1} '.format(i, j))
# debug sys.stderr.write('y: {0} x: {1}n'.format(y, x))
count = self.cell[i 1][j 1]
return count - self.cell[y][x]
class Grid(Grid):
lifeform = ' '
def draw_next(self, term):
new = [([0] * (term.width)) for i in range(term.height)]
for y in range(term.height):
for x in range(term.width):
j = self.neighbor_count(y,x)
if j == 2:
new[y 1][x 1] = self.cell[y 1][x 1]
elif j == 3:
new[y 1][x 1] = 1;
with term.location(x=x, y=y):
echo(self.lifeform)
else:
new[y 1][x 1] = 0
with term.location(x=x, y=y):
echo(' ')
self.cell = new
def main():
"""Program entry point."""
term = Terminal()
y_pos,x_pos = 0,0
def draw(y, x, string):
with term.location(y=y, x=x):
echo(string)
def move(y, x):
echo(term.move(y, x))
grid = Grid(term.height, term.width)
with term.cbreak(), term.fullscreen():
inp, inp0 = '',''
echo(term.clear)
while inp0 not in ('q', 'Q', 'KEY_ESCAPE'):
inp0 = term.inkey() # timeout=1
inp = repr(inp0)
if not inp:
# timeout
break
elif inp0 == ' ':
if grid.toggle_cell(y_pos, x_pos):
draw(y_pos, x_pos, grid.lifeform)
else: draw(y_pos, x_pos, ' ')
elif inp == 'KEY_UP' and y_pos > 0:
y_pos -= 1
move(y_pos, x_pos)
elif inp == 'KEY_DOWN' and y_pos < term.height-1:
y_pos = 1
move(y_pos, x_pos)
elif inp == 'KEY_RIGHT' and x_pos < term.width-1:
x_pos = 1
move(y_pos, x_pos)
elif inp == 'KEY_LEFT' and x_pos > 0:
x_pos -= 1
move(y_pos, x_pos)
elif inp == 'KEY_ENTER':
grid.draw_next(term)
# everything down here was for debugging info
elif inp0 == 'x':
draw(y_pos, x_pos, x_pos)
elif inp0 == 'y':
draw(y_pos, x_pos, y_pos)
elif inp0 == 'w':
draw(y_pos, x_pos, grid.width())
elif inp0 == 'h':
draw(y_pos, x_pos, grid.height())
elif inp0 == 'W':
draw(y_pos, x_pos, term.width)
elif inp0 == 'H':
draw(y_pos, x_pos, term.height)
elif inp0 == 'g':
draw(y_pos, x_pos, term.get_location())
if __name__ == '__main__':
main()
C
#include"life.h"
int main(){
init_win();
game_on = 1; //init_game();
while(game_on){
//get_color();
input();
wrefresh(stdscr);
}
quit();
return 0;
}
void init_win(){
initscr();
nodelay(stdscr,TRUE); // don't block for input, getch()
raw();
cbreak(); // take input chars one at a time, no wait for n
noecho(); // don't print input directly
curs_set(2);
keypad(stdscr,TRUE); // enable keyboard mapping
}
void init_game(){
want_color = 1;
srand(time(NULL));
if (has_colors() amp;amp; want_color) { start_color(); }
for (int i = 0; i < 8; i )
init_pair(i, color_table[i], COLOR_BLACK);
game_on = 1;
}
void input(){
switch(getch()){
case 'q':
nodelay(stdscr,FALSE);
mvprintw(0,0,"Really quit? [y/N]");
refresh();
if(getch()=='y'){
game_on = 0;
}
else{
move(y_pos,x_pos);
refresh();
nodelay(stdscr,TRUE);
}
break;
case 'c':
clear_grid();
break;
case ' ':
toggle_cell(y_pos,x_pos);
break;
case KEY_UP:
if(y_pos > 0){
y_pos--;
move(y_pos,x_pos);
}
break;
case KEY_DOWN:
if(y_pos < LINES-1){
y_pos ;
move(y_pos,x_pos);
}
break;
case KEY_LEFT:
if(x_pos > 0){
x_pos--;
move(y_pos,x_pos);
}
break;
case KEY_RIGHT:
if(x_pos < COLS-1){
x_pos ;
move(y_pos,x_pos);
}
break;
case 10: // 10 == newline
// leaveok(stdscr,1);
update_generation();
move(y_pos,x_pos);
//leaveok(stdscr,0);
break;
}
}
void clear_grid(){
for (int y=0;y<1000;y )
for (int x=0;x<1000;x )
grid[y][x] = 0;
erase();
}
void draw(int y,int x,char z){
move(y,x);
delch();
insch(z);
}
void get_color(){
chtype bold = (rand() % 2) ? A_BOLD : A_NORMAL;
attrset(COLOR_PAIR(rand() % 8) | bold);
}
void toggle_cell(int y,int x){
if (grid[y 1][x 1]==1){
grid[y 1][x 1] = 0;
draw(y,x,' ');
} else {
grid[y 1][x 1] = 1;
draw(y,x,CELL);
}
}
int neighbor_count(int y,int x){
int count = 0;
for(int i=y-1;i<=y 1;i ){
for(int j=x-1;j<=x 1;j ){
count = grid[i 1][j 1];
}
}
count -= grid[y 1][x 1];
return(count);
}
void update_generation(){
int new_grid[1000][1000];
for (int y=0;y<LINES;y )
for (int x=0;x<COLS;x )
switch(neighbor_count(y,x)){
case 2:
new_grid[y 1][x 1] = grid[y 1][x 1];
break;
case 3:
new_grid[y 1][x 1] = 1;
draw(y,x,CELL);
break;
default:
new_grid[y 1][x 1] = 0;
draw(y,x,' ');
}
for (int y=0;y<LINES;y )
for (int x=0;x<COLS;x )
grid[y 1][x 1] = new_grid[y 1][x 1];
}
void quit(){
nocbreak();
echo();
endwin();
}
Комментарии:
1. Если вы находитесь на грани,
x 1
иy 1
попытаетесь прочитать после конца списка (с края доски)… Я давно не писал на C, но я не думаю, что это явная ошибка / error / в C, скорее просто ошибка в вашей программе (если это имеет какой-то смысл). Но это ошибка в Python.2. Почти уверен, что это
grid = Grid(term.height, term.width)
должно бытьgrid = Grid(term.height 2, term.width 2)
. Основываясь наclear_grid
функции, кажется, что вы решили проблему на C, сделавgrid
массив намного больше, чем необходимо.3. Вау. Я знал, что это просто. Думаю, попытка использовать другую структуру и библиотеки немного сбила меня с толку. Я могу сделать массив немного больше с каждой стороны и считать ячейки только в пределах размера терминала. Я увеличил массив в C, чтобы очень просто изменить размер терминала и не иметь дела с выделением памяти, так что это была полная случайность, что все получилось таким образом. Я действительно ценю помощь ваших ребят. Рад, что я спросил. лол