拿一个例子来写写,看看自己的实力,实力之一学就会,一写就废系列。。。。。。看了别人写的三子棋,写了一遍,自己魔改了一下,写了一个双人对战的五子棋。
这是三子棋的代码逻辑:
代码分成三个文件,头文件game.h,存放函数声明和包含的库函数。源文件game.c存放游戏过程中调用的函数,test.c存放主函数即三子棋的运行逻辑;
头文件:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
void initialize_board(char board[ROW][COL], int row, int col);
void display_board(char board[ROW][COL], int row, int col);
void player_play(char board[ROW][COL], int row, int col);
void computer_play(char board[ROW][COL], int row, int col);
char iswin(char board[ROW][COL], int row, int col);
先是需要有三子棋的主菜单,接着就是三子棋游戏部分。首先初始化棋盘,用二维数组设计棋盘,数组中的每个元素其实就对应一个棋盘格,为了让玩家看到棋盘是空的,所以初始化数组就用空格,再就是通过打印分割线,设计棋盘线,这样就能看到棋盘是一格一格的了,设计好了棋盘就需要把整个棋盘打印出来,之后就是玩家下棋,判断输赢,打印棋盘,电脑下棋,判断输赢,打印棋盘,写成死循环,直到电脑和玩家有一方赢就退出循环,逻辑运行代码如下:
#include "game.h"
//三子棋的首菜单
void menu(void)
{
printf("*****************************\n");
printf("********1.开始游戏***********\n");
printf("********0.退出游戏***********\n");
printf("*****************************\n");
}
void game(void)
{
char ret = 0;
char board[ROW][COL] = {0};
//初始化棋盘,不初始化棋盘,后面打印棋盘格,会对不齐
initialize_board(board, ROW, COL);
//打印棋盘格
display_board(board, ROW, COL);
//开始下棋
while (1)
{
player_play(board, ROW, COL);
//需要判断输赢
ret = iswin(board, ROW, COL);
if (ret != 'c')
break;
display_board(board, ROW, COL);
computer_play(board, ROW, COL);
//需要判断输赢
ret = iswin(board, ROW, COL);
if (ret != 'c')
break;
display_board(board, ROW, COL);
}
if (ret == '*')
printf("玩家赢了\n");
else if (ret == '#')
printf("电脑赢了\n");
else
printf("平局\n");
display_board(board, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));//设置随机数的生成起点
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d",&input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入不对,请重新选择\n");
break;
}
} while (input);
return 0;
}
其中的每一个逻辑写成一个函数;其中电脑下棋函数是找棋盘上为空格的地方随机下棋,奈何水平有限,还不会算法,还在初学阶段,能实现随机下棋的这个函数都理解了好一会,rand函数其实也并不能随机,在程序的生命周期里,调用一次rand函数能生成一个与上一次不同的数,但是当程序生命周期结束,在新的一次程序生命周期中调用一次rand函数和上一次程序运行生成的数字是相同的,并没有产生随机数。
srand((unsigned int)time(NULL));//设置随机数的生成起点
rand能产生随机数是基于生成起点的时间来决定的,与srand函数配合使用,srand函数就是设置rand函数随机数的生成起点,电脑并不能想人脑一样凭空就能冒出一个想法,这里指人其实可以凭空想出一个数,这才是随机数,而电脑只能是寻求事件的规律,按照这个规律一丝不苟的执行,对于电脑来说,通过时间所记率的数字是永远不会重复的,记录的这个数字叫时间戳。每执行一次程序,时间必定不同,就会产生不同的时间戳,就能产生不同随机数的生成起点,最终产生伪随机数,我理解的叫伪随机数。time函数返回的类型是无符号整形,所以用(unsigned int)强制类型转换。time函数和指针有关,后面再深入研究一下;
等后期技术深入了再对电脑下棋进行调整一下,不说人工智能水平,至少做到能下赢人的水平。
#include "game.h"
//初始化棋盘
void initialize_board(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
//打印棋盘
void display_board(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)//控制行
{
for (int j = 0; j < col; j++)//控制列
{
//打印数据
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("%c",'|');
}
printf("\n");
//打印分割线
if (i < row - 1)
{
for (int j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("%c",'|');
}
printf("\n");
}
}
}
//玩家下棋
void player_play(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家请下棋\n");
printf("\n");
while (1)
{
printf("请输入坐标:");
scanf("%d %d", &x, &y);
//坐标范围的判定
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判断棋盘上的坐标是否已经被下棋
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("坐标被占用,不能下棋!\n");
}
else
printf("超出范围,请重新输入!\n");
}
}
//电脑下棋
//找没有下棋的坐标随机下棋
void computer_play(char board[ROW][COL], int row, int col)
{
printf("电脑已下棋\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % ROW;
y = rand() % COL;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//棋盘满了返回1,没满返回0
int boardfull(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
/*
判断输赢
玩家赢 *
电脑赢 #
平局 q
游戏继续 c
*/
char iswin(char board[ROW][COL], int row, int col)
{
//行连满3枚棋
for (int i = 0; i < row; i++)
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
//列连满3枚棋
for (int j = 0; j < col; j++)
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
return board[0][j];
//对角线连满3枚棋
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
return board[0][0];
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
return board[0][2];
//没有连满3枚棋
if (boardfull(board, row, col))
//棋盘满了就是平局
return 'q';
else
return 'c';
}
以下是完整五子棋代码:
为了游戏的拓展性,也可以是双人对战的N字棋,N颗棋子相连就可以获胜的游戏规则,修改头文件CHESSNUM符号常量就可以变成N子棋,棋盘的大小也可以改变。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 15
#define COL 15
#define CHESSNUM 5
void initialize_board(char board[ROW][COL], int row, int col);
void display_board(char board[ROW][COL], int row, int col);
void player_play(char board[ROW][COL], int row, int col);
void player_play2(char board[ROW][COL], int row, int col);
char iswin(char board[ROW][COL], int row, int col);
//初始化棋盘
void initialize_board(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
//打印棋盘
void display_board(char board[ROW][COL], int row, int col)
{
//第一行打印棋盘x坐标
for (int m = 0; m < col; m++)
printf(" %2d", m + 1);
printf("\n");
for (int i = 0; i < row; i++)//控制行
{
//第一列打印棋盘y坐标
printf("%2d", i + 1);
for (int j = 0; j < col; j++)//控制列
{
//打印数据
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("%c", '|');
}
printf("\n");
//打印分割线
if (i < row - 1)
{
printf(" ");
for (int j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("%c", '|');
}
printf("\n");
}
}
}
//玩家下棋
void player_play(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("\n");
printf("玩家1请下棋\n");
while (1)
{
printf("请输入坐标:");
scanf("%d.%d", &x, &y);
//坐标范围的判定
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判断棋盘上的坐标是否已经被下棋
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("坐标被占用,不能下棋!\n");
}
else
printf("超出范围,请重新输入!\n");
}
}
//玩家2下棋
void player_play2(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("\n");
printf("玩家2请下棋\n");
while (1)
{
printf("请输入坐标:");
scanf("%d.%d", &x, &y);
//坐标范围的判定
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判断棋盘上的坐标是否已经被下棋
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '#';
break;
}
else
printf("坐标被占用,不能下棋!\n");
}
else
printf("超出范围,请重新输入!\n");
}
}
//棋盘满了返回1,没满返回0
int boardfull(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
/*
判断输赢 写成可以定义连满的棋子数
玩家1赢 *
玩家2赢 #
平局 q
游戏继续 c
*/
char iswin(char board[ROW][COL], int row, int col)
{
//行连满
for (int i = 0; i < row; i++)
{
for (int j = 0; j <= col - CHESSNUM; j++)
{
int count = 1;
for (int k = 1; k < CHESSNUM; k++)
{
if (board[i][j] == board[i][j + k] && board[i][j] != ' ')
count++;
}
if (count == CHESSNUM)
return board[i][j];
}
}
//列连满
for (int i = 0; i <= row - CHESSNUM; i++)
{
for (int j = 0; j < col; j++)
{
int count = 1;
for (int k = 1; k < CHESSNUM; k++)
{
if (board[i][j] == board[i + k][j] && board[i][j] != ' ')
count++;
}
if (count == CHESSNUM)
return board[i][j];
}
}
//对角线连满
for (int i = 0; i <= row - CHESSNUM; i++)
{
for (int j = 0; j <= col -CHESSNUM; j++)
{
int count = 1;
for (int k = 1; k < CHESSNUM; k++)
{
if (board[i][j] == board[i + k][j + k] && board[i][j] != ' ')
count++;
}
if (count == CHESSNUM)
return board[i][j];
}
}
for (int i = 0; i <= row - CHESSNUM; i++)
{
for (int j = col-1; j >= CHESSNUM - 1; j--)
{
int count = 1;
for (int k = 1; k < CHESSNUM; k++)
{
if (board[i][j] == board[i + k][j - k] && board[i][j] != ' ')
count++;
}
if (count == CHESSNUM)
return board[i][j];
}
}
//没有连满
if (boardfull(board, row, col))
//棋盘满了就是平局
return 'q';
else
return 'c';
}
//首菜单
void menu(void)
{
printf(" \n");
printf("*****************************\n");
printf("********1.开始游戏***********\n");
printf("********0.退出游戏***********\n");
printf("*****************************\n");
printf(" \n");
}
void game(void)
{
char ret = 0;
char board[ROW][COL] = { 0 };
//初始化棋盘,不初始化棋盘,后面打印棋盘格,会对不齐
initialize_board(board, ROW, COL);
//打印棋盘格
display_board(board, ROW, COL);
//开始下棋
while (1)
{
player_play(board, ROW, COL);
//需要判断输赢
ret = iswin(board, ROW, COL);
if (ret != 'c')
break;
display_board(board, ROW, COL);
player_play2(board, ROW, COL);
//需要判断输赢
ret = iswin(board, ROW, COL);
if (ret != 'c')
break;
display_board(board, ROW, COL);
}
if (ret == '*')
printf("玩家1赢了\n");
else if (ret == '#')
printf("玩家2赢了\n");
else
printf("平局\n");
display_board(board, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));//设置随机数的生成起点
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入不对,请重新选择\n");
break;
}
} while (input);
return 0;
}