设计一个小游戏其实是对自己掌握一门编程语言的一个升华,几百行代码分项目进行这种很让人着迷的感觉哦!
与五子棋游戏其实本质区别只不过是判输赢的条件不同,这里我打算写写三子棋小游戏。
代码的最后我将所有源代码整理了,大家急用可以直接复制哦不过要记得分项目哦。
本文的三子棋代码修改只需要改一下一些关于判输赢条件即可 棋盘大小可以自由修改。
一.程序设计
写这样的一个小游戏项目-----先要进行设计:
1.数据结构
2.整体规划
3.接口设计
4.实现具体功能
1.1数据结构以及接口
存放棋盘上的棋子我们可以用*和#来代替,所以这样了棋盘存放棋子的数据机构可以用数组 下面我用静态数组形式实现 -------形式为 char Broad[ROW][COL] ; 当棋盘对应的棋子为空格表示这个位置不就是空位置么。
1.2整体规划
![](https://i-blog.csdnimg.cn/direct/a257f67730ee4ad5996558c868e5648b.png)
2. 棋盘创建
enum Choice {
Exit,
Play
};
menu()
{
printf("*******************\n");
printf("*****0.exit********\n");
printf("*****1.paly********\n");
printf("*******************\n");
printf("*******************\n");
}
void game()
{
char Board[ROW][COL] = { 0 };
int size = 0;// 用来后续判满
BoardInit(Board);
BoardPrint(Board);
}
int main() {
enum Choice input = 0;
do
{
menu();
scanf("%d", &input);
switch (input) {
case Exit:
printf("hehe");
break;
case Play:
game();
break;
default:
printf("请输入正确选项>.");
}
} while (input);
return 0;
}
![](https://i-blog.csdnimg.cn/direct/f9fcb7eb401946ee866c0d8257343722.png)
![](https://i-blog.csdnimg.cn/direct/5a9242bd54aa4277bad01b3753b4b992.png)
3.玩家和电脑
tip:其实二者思路都很简单只需要将棋盘的数据结构修改进行 (这里是数组) 说白了就是将数组中的元素修改
![](https://i-blog.csdnimg.cn/direct/be580cd71dd241e1ac43f37c5c612072.png)
![](https://i-blog.csdnimg.cn/direct/5b27256a9e644c81b6ee7f6d48d8936d.png)
4.判断输赢情况:
ISwin函数
输赢情况:
1.一个是对角线三子合一
2.或者是某一行或者某一列
3. 满了而且和了
行列判断: 根据他的连续性
思路:根据连续性我们固定行不动 遍历列上所有点 创建一个flag 只有当棋子相同且连续才++否则就重新赋值为0 这样就可以记录输赢了。
行和列的判赢思路是类似的下面是具体实现:
任意一个点都判断它关于对角线的关系: ----要知道对角线中的元素 行和列都相差一个同样的分量 。
![](https://i-blog.csdnimg.cn/direct/75db8c87db8d4e1f8110f0bd9a848de9.png)
![](https://i-blog.csdnimg.cn/direct/89ac61e092f9426f8549b938ca90299b.png)
![](https://i-blog.csdnimg.cn/direct/05eb319ebcc94323b26bfc50ca3f5592.png)
最后是判满 其实判满很简单 :
1. 既然一直没赢满了就和
2. 刚好下了就满了
我这里甚至没有单独写一个判满函数 而是直接这样是因为我提前做了逻辑判断
就两种情况 因为如果是下最后一个满棋这里是先判输赢在判满 所以赢在前 就直接结束了
如果没有结果在用判满 和了
-------------我们前面指定了一个size就是拿来判满的。
![](https://i-blog.csdnimg.cn/direct/b35675ed531943a78e6a48befa738a0f.png)
五.程序优缺以及实现状况
实现情况:接下来我们来验证一下
尝试:
![](https://i-blog.csdnimg.cn/direct/8c2da2e3b85d4d24a1e3b1fc34a2a41d.png)
行胜利情况:
![](https://i-blog.csdnimg.cn/direct/e793b479c59b4d45b4525aed473bd1e8.png)
列:
![](https://i-blog.csdnimg.cn/direct/a43f397e8d5143cfa403fa962fd1521a.png)
对角线胜利
![](https://i-blog.csdnimg.cn/direct/a47b75d016b345bcaa7e2390a6ef4815.png)
六.项目具体实现
朋友们需要的直接拿走吧,但是麻烦给我一个小小的赞和关注作为鼓励呢!
game.h
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 5
#define COL 5
void BoardInit(char(*Board)[COL]);
void BoardPrint(char(*Board)[COL]);
void PeopleMove(char(*Board)[COL], int* size);
void ComputerMove(char(*Board)[COL],int*size);
char IsWin(char(*Board)[COL]);
int IsFull(int* size);
game.c
#include"game.h"
void BoardInit(char(*Board)[COL])
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
Board[i][j] = ' ';
}
}
}
void BoardPrint(char(*Board)[COL])
{
for (int i = 0; i < ROW; i++)
{
printf("_______________________________\n");
for (int j = 0; j < COL; j++)
{
printf("| ");
printf("%c", Board[i][j]);// | * | * | * | * |
printf(" "); // _________________________
if (j == COL-1)
printf("|");
}
printf("\n");
if(i==ROW-1)
printf("_______________________________\n");
}
}
void PeopleMove(char(*Board)[COL],int*size)
{
int x = 0;
int y = 0;// 坐标
printf("玩家输入坐标:");
scanf("%d %d",&x,&y);
x--;
y--;
if(x<ROW&&x>=0&&y<COL&&y>=0)
Board[x][y] = '*';
(*size)++;
}
void ComputerMove(char(*Board)[COL],int* size)
{
int x = 0;
int y = 0;// 坐标
while (1)
{
x = rand() % ROW;
y = rand() % COL;
if (Board[x][y] == ' ') {
Board[x][y] = '#';
(*size)++;
break;
}
}
}
int Diag(char(*Board)[COL], int row,int col,int dr, int dc)
{
char point = Board[row][col];
if (point == ' ')
return 0;
int count = 0;
for (int i = 0; i < 3; i++)
{
int r = row + dr * i;
int c = col + dc * i;
if (r < 0 || r >= ROW || c < 0 || c >= ROW || Board[r][c] != point)
return 0;
count++;
}
return count == 3;
}
char IsWin(char(*Board)[COL])
{
// 行满
// 方向确定为从上往下
for (int i = 0; i < ROW; i++)
{
int flag = 0;
int j = 1;
for (j; j < COL; j++)
{
if (Board[i][j] != Board[i][j - 1])// * * ***
{
flag = 0;
}
if (Board[i][j] == Board[i][j - 1] && Board[i][j] != ' ')
{
flag++;
if (flag == 2)
return Board[i][j];
}
}
}
// 列
for (int i = 0; i < COL; i++)
{
int flag = 0;
int j = 1;
for ( j ; j < ROW; j++)
{
if (Board[j-1][i] != Board[j][i])
{
flag = 0;
}
if (Board[j-1][i] == Board[j][i]&&Board[j][i]!=' ')
{
flag++;
if (flag == 2)
return Board[j][i];
}
}
}
// 对角线判
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
// 每一个点左上到右下 右上到左下
if (Diag(Board, i, j, 1, -1) || Diag(Board, i, j, 1, 1))
{
return Board[i][j];
}
}
}
return ' ';
}
int IsFull(int* size)
{
return size == COL * ROW;
}
test.c
#include"game.h"
enum Choice {
Exit,
Play
};
menu()
{
printf("*******************\n");
printf("*****0.exit********\n");
printf("*****1.paly********\n");
printf("*******************\n");
printf("*******************\n");
}
void game()
{
char Board[ROW][COL] = { 0 };
int size = 0;// 用来后续判满
BoardInit(Board);
BoardPrint(Board);
srand((unsigned int)time(NULL));
while (1) {
if (IsWin(Board)!=' ')
{
if (IsWin(Board) == '*')
printf("玩家获胜\n");
else
printf("电脑获胜\n");
return;
}
if (size == ROW * COL) {
printf("和了\n");
return;
}
PeopleMove(Board, &size);
BoardPrint(Board);
printf("\n电脑操作:\n");
ComputerMove(Board, &size);
BoardPrint(Board);
}
}
int main() {
enum Choice input = 0;
do
{
menu();
scanf("%d", &input);
switch (input) {
case Exit:
printf("hehe");
break;
case Play:
game();
break;
default:
printf("请输入正确选项>.");
}
} while (input);
return 0;
}