# mini-riscv-os vga Conway's Game of Life
前面作者實現了碎形圖
https://zh.wikipedia.org/wiki/%E5%88%86%E5%BD%A2
那我們就來在上面實現一個生命遊戲
https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
https://github.com/alnvdl/Life
這是一個簡單的c 生命遊戲可以觀察每一個步驟,我們目前專案,還沒實現動態分配記憶體,contex switch 好像也沒保存記憶體狀態,我們直接把專案中的array 改為 靜態宣告
https://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/
```c=
#include "os.h"
#include <stdio.h>
#include <stdlib.h>
//#include<string.h>
#define WIDTH 250
#define HEIGHT 200
#define ACTIVE 1
#define INACTIVE 0
#define ACTIVE_SYMBOL '*'
#define INACTIVE_SYMBOL ' '
int *arr[320*200];
void *next[320*200];
void *memset(void *dst, int c, size_t n)
{
char *q = dst;
char *end = q + n;
for (;;)
{
if (q >= end)
break;
*q++ = (char)c;
if (q >= end)
break;
*q++ = (char)c;
if (q >= end)
break;
*q++ = (char)c;
if (q >= end)
break;
*q++ = (char)c;
}
return dst;
}
int count_neighbors(int *board, int x, int y)
{
/*
Counts the number os neighbors for a given cell.
board: the board
x: the cell's horizontal coordinate
y: the cell's vertical coordinate
*/
int i, j, count = 0;
for (i = -1; i <= 1; i++)
for (j = -1; j <= 1; j++)
if (!(i == 0 && j == 0) &&
(x + i >= 0 && x + i < WIDTH) &&
(y + j >= 0 && y + j < HEIGHT) &&
(board[(x + i) * WIDTH + (y + j)] == ACTIVE))
count++;
return count;
}
int count_active(int *board)
{
/*
Counts the number os active cells on the board.
board: the board
*/
int i, j, count = 0;
for (i = 0; i < WIDTH; i++)
for (j = 0; j < HEIGHT; j++)
if (board[i * WIDTH + j] == ACTIVE)
count++;
return count;
}
void iter_cell(int *board, int *next, int x, int y)
{
/*
Sets the state of the cell based on the game rules.
board: the curent iteration board
next: the next iteration board
x: the cell's horizontal coordinate
y: the cell's vertical coordinate
*/
int current_state = board[x * WIDTH + y];
int n_neighbors = count_neighbors(board, x, y);
if (current_state == ACTIVE && n_neighbors < 2)
next[x * WIDTH + y] = INACTIVE;
else if (current_state == ACTIVE && n_neighbors > 3)
next[x * WIDTH + y] = INACTIVE;
else if (current_state == ACTIVE && (n_neighbors == 2 || n_neighbors == 3))
next[x * WIDTH + y] = ACTIVE;
else if (current_state == INACTIVE && n_neighbors == 3)
next[x * WIDTH + y] = ACTIVE;
else
next[x * WIDTH + y] = INACTIVE;
}
void init_board(int *arr)
{
/*
Initializes the board cells to a inactive state.
board: the curent iteration board
*/
for (int i = 0; i < WIDTH ; i++)
{
for (int j = 0; j < HEIGHT; j++)
// lib_printf("%d ", arr[i * y + j]);
arr[i * WIDTH + j] = 0;
// lib_printf("\n");
}
}
void copy_board(int *source, int *destination)
{
/*
Copies the a source board cells to a destination board.
source: the source board
destination: the destination board
*/
for (int i = 0; i < WIDTH ; i++)
for (int j = 0; j < HEIGHT; j++)
destination[i * WIDTH + j] = source[i * WIDTH + j];
}
void next_iteration(int *arr)
{
/*
Iterates the given board to its next state.
board: the curent iteration board
*/
// x*y
//void *next[WIDTH * HEIGHT];
init_board(next);
for (int i = 0; i < WIDTH; i++)
for (int j = 0; j < HEIGHT; j++)
iter_cell(arr, next, i, j);
copy_board(next, arr);
}
void print_board(int *arr)
{
/*
Outputs the board.
board: the board
*/
for (int i = 0; i < WIDTH; i++)
{
for (int j = 0; j < HEIGHT; j++)
{
if (arr[i * WIDTH + j] == INACTIVE)
putpixel(i, j, 0x000000);
// printf("%c ", INACTIVE_SYMBOL);
else
putpixel(i, j, 0x0000ff);
// printf("%c ", ACTIVE_SYMBOL);
}
// printf("\n");
}
}
void system_clear()
{
/*
Clears the output.
FIXME: not portable
*/
// system("clear");
for (int i = 0; i < WIDTH; i++)
for (int j = 0; j < HEIGHT; j++)
{
putpixel(i, j, 0x000000);
}
}
void redraw(int *arr, char *shell, int gen_count,
int active_count)
{
/*
Redraws the content of the game.
board: the board to print
shell: the message to ask for input
gen_count: generation (iteration) count
active_count: the number of active cells
*/
system_clear();
// printf("\n%d generations; %d active cells (%dx%d board)\n", gen_count,
// active_count,
// WIDTH, HEIGHT);
print_board(arr);
// printf("%s: ", shell);
}
void show_help()
{
}
void show_cell_info(int board[HEIGHT][WIDTH], int x, int y)
{
int internal_x = (HEIGHT - y), internal_y = (x - 1);
}
void user_task0(void)
{
lib_puts("Task0: Created!\n");
lib_puts("Task0: Now, return to kernel mode\n");
os_kernel();
while (1)
{
lib_puts("Task0: Running...\n");
lib_delay(10);
os_kernel();
}
}
void user_task1(void)
{
lib_puts("Task1: Created!\n");
lib_puts("Task1: Now, return to kernel mode\n");
os_kernel();
int x =HEIGHT, y = WIDTH;
int gen_count = 0, active_count = 0;
init_board(arr);
for (int i = 0 ; i <x ; i++)
for (int j = 0 ; j <y ; j++){
if((i* y )%2 == 0)
arr[i* y + j] = 1;
if((j*x*y*i )%2 == 2)
arr[i* y + j] = 1;
}
arr[20 * y + 20] = 1;
arr[21 * y + 19] = 1;
arr[20 * y + 18] = 1;
arr[21 * y + 18] = 1;
arr[19 * y + 18] = 1;
arr[20 * y + 20] = 1;
arr[21 * y + 19] = 1;
arr[20 * y + 18] = 1;
arr[21 * y + 18] = 1;
arr[19 * y + 18] = 1;
arr[12 * y + 16] = 1;
arr[13 * y + 16] = 1;
arr[14 * y + 16] = 1;
arr[10 * y + 14] = 1;
arr[10 * y + 13] = 1;
arr[10 * y + 12] = 1;
arr[15 * y + 14] = 1;
arr[15 * y + 13] = 1;
arr[15 * y + 12] = 1;
arr[12 * y + 11] = 1;
arr[13 * y + 11] = 1;
arr[14 * y + 11] = 1;
arr[18 * y + 11] = 1;
arr[19 * y + 11] = 1;
arr[20 * y + 11] = 1;
arr[17 * y + 14] = 1;
arr[17 * y + 13] = 1;
arr[17 * y + 12] = 1;
arr[22 * y + 14] = 1;
arr[22 * y + 13] = 1;
arr[22 * y + 12] = 1;
arr[18 * y + 11] = 1;
arr[18 * y + 11] = 1;
arr[18 * y + 11] = 1;
arr[12 * y + 9] = 1;
arr[13 * y + 9] = 1;
arr[14 * y + 9] = 1;
arr[10 * y + 8] = 1;
arr[10 * y + 7] = 1;
arr[10 * y + 6] = 1;
arr[15 * y + 8] = 1;
arr[15 * y + 7] = 1;
arr[15 * y + 6] = 1;
arr[12 * y + 4] = 1;
arr[13 * y + 4] = 1;
arr[14 * y + 4] = 1;
arr[18 * y + 9] = 1;
arr[19 * y + 9] = 1;
arr[20 * y + 9] = 1;
arr[17 * y + 8] = 1;
arr[17 * y + 7] = 1;
arr[17 * y + 6] = 1;
arr[22 * y + 8] = 1;
arr[22 * y + 7] = 1;
arr[22 * y + 6] = 1;
arr[18 * y + 4] = 1;
arr[19 * y + 4] = 1;
arr[20 * y + 4] = 1;
redraw(arr, "x,y", gen_count, active_count);
next_iteration(arr);
// redraw(arr, "x,y", gen_count, active_count);
// next_iteration(arr);
while (1)
{
lib_puts("Task1: Running...\n");
lib_delay(10);
// os_kernel();
redraw(arr, "x,y", gen_count, active_count);
next_iteration(arr);
// next_iteration(board);
// active_count = count_active(board);
// gen_count++;
}
}
void user_init()
{
task_create(&user_task0);
task_create(&user_task1);
}
```
生命遊戲有一個太空船和作者給的範例test case,我們把它直接轉為array
現在我們直接就在這個os上實現一個生命遊戲!
https://gist.github.com/x213212/a16312fb476427a14cb63e6484b31ae5
![](https://i.imgur.com/NLA5GAz.gif)
改個解析度
![](https://i.imgur.com/meQQr1N.gif)