这个简单的小游戏一定要会!使用C语言实现三子棋游戏
Posted ✯ SwaggerHYH
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了这个简单的小游戏一定要会!使用C语言实现三子棋游戏相关的知识,希望对你有一定的参考价值。
目录
一、游戏简介
三子棋是黑白棋的一种。三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉、一条龙、井字棋等。将正方形对角线连起来,相对两边依次摆上三个双方棋子,只要将自己的三个棋子走成一条线,对方就算输了。但是,有很多时候会出现和棋的情况。
二、游戏设计
2.1 棋盘设计
利用字符串,在屏幕上打印出一个‘#’号,作为游戏棋盘。(效果图如下)
2.2 模型设计
三、游戏实现
3.1 SanZiQiMain.c
3.1.1 main(主模块)
(1)模块功能及思路:本模块为程序的入口,通过此模块调入菜单,执行开始游戏或退出游戏的功能。同时也负责rand()函数的配置,rand()函数在之后生成随机数时需要调用,配置其的方法是在主模块中使用时间戳作为srand()函数的参数,这是编写本模块的要点,其它部分的编写思路较为简单,只需利用switch语句进行设计即可。
(2)模块代码:
int main()
{
int flag = 0;
do
{
srand((unsigned int)time(NULL));
switch (flag = choiceMenu())
{
case 0:printf("退出游戏\\n"); break;
case 1:game();break;
default:printf("输入错误,请重新选择!\\n"); break;
}
} while (flag);
return 0;
}
3.1.2 choiceMenu(开始菜单)
(1)模块功能及思路:该函数负责打印游戏开始菜单,同时需要返回玩家的选项值。
(2)模块代码:
int choiceMenu()
{
int input = 0;
printf("********************************\\n");
printf("***********1. 开始游戏**********\\n");
printf("***********0. 退出游戏**********\\n");
printf("********************************\\n");
printf("请选择>");
scanf("%d", &input);
return input;
}
3.2 Game.c
3.2.1 game(游戏执行)
(1)模块功能及思路:本模块负责游戏的执行。游戏执行的顺序为:显示棋盘——>玩家下棋——>显示棋盘——>判断是否赢棋——>电脑下棋——>显示棋盘——>判断是否赢棋……该过程在未区分出输赢之前应处在一个循环体之中。在此之前,我们还需要一个二维数组来存放每次下棋操作后的棋子信息,为了提高代码的复用性,数组的行与列采用宏定义的方式进行配置,同时这也是棋盘的行与列,之后将多次使用。为了方便管理,将其定义在Game.h文件下。
#define ROW 3
#define COL 3
由于显示棋盘时,需要打印二维数组中的内容,在第一次显示棋盘前,应当先对二维数组进行初始化,将其内部元素均置为‘ ’(空格)。
同时,在跳出循环体后,因根据赢棋判断函数打印出输赢信息,一轮游戏也就到此结束。
(2)模块代码:
void game()
{
system("cls");
char ret = 0;
char board[ROW][COL];
boardInit(board, ROW, COL);//初始化数组
displayBoard(board, ROW, COL);//显示棋盘
while (1)
{
playerMove(board, ROW, COL);//玩家下棋
displayBoard(board, ROW, COL);//显示棋盘
ret = isWin(board, ROW, COL);
if (ret != 'C')
{
break;
}//判断输赢
computerMove(board, ROW, COL);//电脑下棋
displayBoard(board, ROW, COL);//显示棋盘
ret = isWin(board, ROW, COL);
if (ret != 'C')
{
break;
}//判断输赢
}
if (ret == '*')
{
printf("您赢了\\n");
}
else if (ret == '#')
{
printf("您输了\\n");
}
else
{
printf("平局\\n");
}
}
3.2.2 boardInit(初始化数组)
(1)模块功能及思路:本模块要执行的是对数组的初始化。思路也非常简单,只需要利用循环对二维数组进行遍历即可。
(2)模块代码:
void boardInit(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
3.2.3 displayBoard(显示棋盘)
(1)模块功能及思路:在编写代码之前,已经设计好了棋盘。本函数只需按照固定格式打印出棋盘即可。难点在于根据行与列的值找到找到打印循环的规律。列入3x3时,每行打印的数据为3个,只需循环col次,而每行的分割线‘|’只需打印2次,所以只需要循环col-1次。打印行分割线时同理,最后一行的数据下面不需要分割线,因此在打印前判断i是否小于row-1即可。
(2)模块代码:
void displayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\\n");
}
}
3.2.4 playerMove(玩家下棋)
(1)模块功能及思路:本模块执行的功能为玩家下棋,只需调整二维数组中的数据即可。需要注意的是判断输入数据是否合法(不超出行与列)与判断所下位置是否已被占用。
同时,为了取得更好的游玩效果,可以在适当的时候调用system("cls")进行清屏幕,使得游玩时显示的效果就是像在固定的棋盘上放下棋子,而不是刷新整个棋盘。
(2)模块代码:
void playerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
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] != ' ')
{
printf("坐标已占用,请重新输入\\n");
}
else
{
board[x - 1][y - 1] = '*';
system("cls");
break;
}
}
else
{
printf("坐标输入错误,请重新输入\\n");
}
}
}
3.2.5 computerMove(电脑下棋)
(1)模块功能及思路:基本思路与玩家下棋相似,重点在与如何使得计算机的到落子的坐标。这里就要运用到之前提到的rand()函数了,经过配置后,每次调用rand()函数会获取到一个随机值,而本模块所需要的随机值在0~2之间,所以只需利用%运算符即可。同理为了取得更好的游戏效果,添加了清屏代码与延时代码Sleep(1000)(用于模拟电脑思考时间)。
(2)模块代码:
void computerMove(char board[ROW][COL], int row, int col)
{
printf("电脑走:\\n");
Sleep(1000);
while (1)
{
int x = rand() % 3;
int y = rand() % 3;
if (board[x][y] == ' ')
{
board[x][y] = '#';
system("cls");
break;
}
}
}
3.2.6 isWin(判断赢棋)
(1)模块功能及思路:本模块的返回值有四个方向:1.玩家赢;2.电脑赢;3.平局;4.游戏继续。
若在一次落子后,一方取得了胜利,则情况必为三横行、三竖行、两斜行中的一种,只需利用判断语句进行判断即可。同时若玩家获胜则返回*,电脑获胜则返回#(便于代码书写)。
若没有赢棋,则判断是否平局,只需要遍历数组判断其值是否均不为空格即可。
其它情况则游戏继续。
(2)模块代码:
char isWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int flag = 1;
for (i = 0; i < row; i++)
{
if (board[i][0] != ' ' && board[i][0] == board[i][1] && board[i][0] == board[i][2])
{
return board[i][0];
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] != ' ' && board[0][i] == board[1][i] && board[0][i] == board[2][i])
{
return board[0][i];
}
}
if (board[0][0] != ' ' && board[0][0] == board[1][1] && board[0][0] == board[2][2])
{
return board[0][0];
}
if (board[2][0] != ' ' && board[2][0] == board[1][1] && board[2][0] == board[0][2])
{
return board[2][0];
}
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
flag = 0;
break;
}
}
}
if (flag)
{
return 'P';
}
return 'C';
//1. 判断输赢*/#
//2. 判断平局P
//3. 游戏继续C
}
四、游戏测试
五、游戏代码
3.1 SanZiQiMain.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Game.h"
int choiceMenu()
{
int input = 0;
printf("********************************\\n");
printf("***********1. 开始游戏**********\\n");
printf("***********0. 退出游戏**********\\n");
printf("********************************\\n");
printf("请选择>");
scanf("%d", &input);
return input;
}
int main()
{
int flag = 0;
do
{
srand((unsigned int)time(NULL));
switch (flag = choiceMenu())
{
case 0:printf("退出游戏\\n"); break;
case 1:game();break;
default:printf("输入错误,请重新选择!\\n"); break;
}
} while (flag);
return 0;
}
3.2 Game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Game.h"
void boardInit(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void displayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\\n");
}
}
void playerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
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] != ' ')
{
printf("坐标已占用,请重新输入\\n");
}
else
{
board[x - 1][y - 1] = '*';
system("cls");
break;
}
}
else
{
printf("坐标输入错误,请重新输入\\n");
}
}
}
void computerMove(char board[ROW][COL], int row, int col)
{
printf("电脑走:\\n");
Sleep(1000);
while (1)
{
int x = rand() % 3;
int y = rand() % 3;
if (board[x][y] == ' ')
{
board[x][y] = '#';
system("cls");
break;
}
}
}
char isWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int flag = 1;
for (i = 0; i < row; i++)
{
if (board[i][0] != ' ' && board[i][0] == board[i][1] && board[i][0] == board[i][2])
{
return board[i][0];
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] != ' ' && board[0][i] == board[1][i] && board[0][i] == board[2][i])
{
return board[0][i];
}
}
if (board[0][0] != ' ' && board[0][0] == board[1][1] && board[0][0] == board[2][2])
{
return board[0][0];
}
if (board[2][0] != ' ' && board[2][0] == board[1][1] && board[2][0] == board[0][2])
{
return board[2][0];
}
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
flag = 0;
break;
}
}
}
if (flag)
{
return 'P';
}
return 'C';
//1. 判断输赢*/#
//2. 判断平局P
//3. 游戏继续C
}
void game()
{
system("cls");
char ret = 0;
char board[ROW][COL];
boardInit(board, ROW, COL);//初始化数组
displayBoard(board, ROW, COL);//显示棋盘
while (1)
{
playerMove(board, ROW, COL);//玩家下棋
displayBoard(board, ROW, COL);//显示棋盘
ret = isWin(board, ROW, COL);
if (ret != 'C')
{
break;
}//判断输赢
computerMove(board, ROW, COL);//电脑下棋
displayBoard(board, ROW, COL);//显示棋盘
ret = isWin(board, ROW, COL);
if (ret != 'C')
{
break;
}//判断输赢
}
if (ret == '*')
{
printf("您赢了\\n");
}
else if (ret == '#')
{
printf("您输了\\n");
}
else
{
printf("平局\\n");
}
}
3.3 Game.h
#pragma once
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <windows.h>
#define ROW 3
#define COL 3
void game();
以上是关于这个简单的小游戏一定要会!使用C语言实现三子棋游戏的主要内容,如果未能解决你的问题,请参考以下文章