还有这事?——一小时学会三子棋(优化版)
Posted coder_Xwl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了还有这事?——一小时学会三子棋(优化版)相关的知识,希望对你有一定的参考价值。
前情提要
在学习了数组之后,我们了解了数组的创建,掌握了数组在内存中的存放,也认识到了一维数组和二维数组的结构,因此,下面就让我们用二维数组来实战一下,利用所学,实现一个简易的三子棋游戏,Let’s go。
一.代码展示部分
三子棋.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void game()
{
int tmp;
char board[ROW][COL];
initialboard(board);//棋盘初始化
printboard(board, ROW, COL);//打印棋盘
while (1)//下多次
{
printf("玩家下棋:\\n");
playermove(board, ROW, COL);
printboard(board, ROW, COL);
tmp = judgefull(board, ROW, COL);
if (tmp == 0)
{
printf("棋盘已满\\n");
break;
}
tmp = judgewin(board, ROW, COL);
if (tmp == 0)
{
printf("玩家胜!\\n");
break;
}
printf("电脑下棋:\\n");
computermove(board, ROW, COL);
printboard(board, ROW, COL);
tmp = judgefull(board, ROW, COL);
if (tmp == 0)
{
printf("棋盘已满\\n");
break;
}
tmp = judgewin(board, ROW, COL);
if (tmp == 0)
{
printf("电脑胜!\\n");
break;
}
}
}
void menu()
{
printf("************************\\n");
printf("******* 1.play *******\\n");
printf("******* 0.exit *******\\n");
printf("************************\\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择>: ");
scanf("%d", &input);
switch (input)
{
case 1:
{
game();
break;
}
case 0:
{
printf("退出成功\\n");
break;
}
default:
{
printf("选择错误,请重新选择!\\n");
}
}
} while (input);
return 0;
}
game.c
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"//引头文件
void initialboard(char board[ROW][COL])
{
int i, j;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
board[i][j] = ' ';
}
}
}
//棋盘初始化
void printboard(char board[ROW][COL], int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
{
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 i, j;
printf("请输入您要下的位置坐标>:");
scanf("%d%d", &i, &j);
if (i >= 1 && i <= row&&j >= 1 && j <= col)
{
if (board[i - 1][j - 1] == ' ')
{
board[i - 1][j - 1] = '*';
}
else
{
printf("此坐标对应位置已被下过,请重下!\\n");
}
}
else
{
printf("坐标非法,请重新输入!\\n");
}
}
//玩家下棋
void computermove(char board[ROW][COL], int row, int col)
{
int i, j;
while (1)
{
i = rand() % row;//生成随机坐标
j = rand() % col;
if (board[i][j] == ' ')
{
board[i][j] = '!';
break;
}
}
}
//电脑下棋
int judgefull(char board[ROW][COL], int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 1;
}
}
return 0;
}
//判断棋盘是否下满
int judgewin(char board[ROW][COL], int row, int col)
{
int i, j, k;
for (i = 0; i < row; i++)//行
{
for (j = 0; j < col - 2; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] != ' ')
return 0;
}
}
for (i = 0; i < col; i++)//列
{
for (j = 0; j < row - 2; j++)
{
if (board[j][i] == board[j + 1][i] && board[j][i] == board[j + 2][i] && board[j][i] != ' ')
return 0;
}
}
for (i = 0; i < row - 2; i++)//主对角线
{
for (j = i; j < col - 2; j++)
{
if (board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ')
return 0;
}
}
for (i = 0; i < row - 2; i++)//副对角线
{
for (j = col - i; j > 1; j--)
{
if (board[i][j] == board[i + 1][j - 1] && board[i][j] == board[i + 2][j - 2] && board[i][j] != ' ')
return 0;
}
}
for (i = 1; i < row - 2; i++)//主对角线下部分
{
for (j = 0, k = i; j < col - 2; j++)
{
if (i - j == k)
{
if (board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ')
return 0;
}
}
}
for (j = 1; j < col - 2; j++)//主对角线上部分
{
for (i = 0, k = j; i < row - 2; i++)
{
if (j - i == k)
{
if (board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ')
return 0;
}
}
}
for (i = 0; i < row - 2; i++)//副对角线上部分
{
for (j = col - 2, k = j; j > 1; j--)
{
if (i + j == k)
{
if (board[i][j] == board[i + 1][j - 1] && board[i][j] == board[i + 2][j - 2] && board[i][j] != ' ')
return 0;
}
}
}
for (i = row - 1, k = 1; i > 1; i--, k++)//副对角线下部分
{
for (j = k; j < col - 2; j++)
{
if (board[i][j] == board[i - 1][j + 1] && board[i][j] == board[i - 2][j + 2] && board[i][j] != ' ')
return 0;
}
}
}
//判断输赢
game.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <stdlib.h>
#include<time.h>
#define ROW 5
#define COL 5
void game();
//游戏声明
void initialboard(char board[ROW][COL]);
//棋盘初始化声明
void printboard(char board[ROW][COL], int row, int col);
//棋盘打印声明
void playermove(char board[ROW][COL], int row, int col);
//玩家下棋声明
void computermove(char board[ROW][COL], int row, int col);
//电脑下棋声明
int judgefull(char board[ROW][COL], int row, int col);
//判断棋盘是否满了
int judgewin(char board[ROW][COL], int row, int col);
//判断输赢
当看到这一堆的代码时,想必大家脑袋瓜子嗡嗡的吧!
没关系,下面我带大家逐句理解。
二.分析代码部分
由于实现三子棋较为复杂,代码量相对比较多,所以我们分模块来写。三子棋总的有三个模块——三子棋.c、game.c、game.h。
模块 | 功能 |
---|---|
三子棋.c | 主要实现三子棋游戏的逻辑和结构 |
game.c | 主要实现三子棋游戏的具体实现 |
game.h | 定义声明三子棋的所用到函数 |
[1]三子棋.c部分
既然在三子棋.c模块下我们要实现三子棋游戏的逻辑和结构,所以游戏执行的流程我们一定要清楚。
试想一下,我们在玩游戏的时候,最先看到的是一个游戏的界面,界面上有一个选项卡供我们选择,我们可选择开始游戏或是退出游戏。并且,一旦开始游戏,我们可以玩好几把,也可以选择退出游戏。
想到这,我们大概就知道这里要用到循环语句和分支语句。那么下面让我们来实现一下:
void menu()//选项卡
{
printf("************************\\n");
printf("******* 1.play *******\\n");
printf("******* 0.exit *******\\n");
printf("************************\\n");
}
int main()
{
int input = 0;
do//玩很多把
{
menu();
printf("请选择>: ");
scanf("%d", &input);
switch (input)
{
case 1://进入游戏
{
game();
break;
}
case 0://退出游戏
{
printf("退出成功\\n");
break;
}
default:
{
printf("选择错误,请重新选择!\\n");
}
}
} while (input);//若input=0,判以上是关于还有这事?——一小时学会三子棋(优化版)的主要内容,如果未能解决你的问题,请参考以下文章