两位玩家轮流在棋盘上放置不同颜色的棋子,一位玩家使用黑子,另一位使用白子,棋盘是一个偶数正方形。

  只能将一个棋子放在对手的棋子旁边,使对手在水平、垂直、对角线方向上的棋子变成自己的棋子,游戏结束时,棋子多的玩家获胜。

  如果所有的方格都放置了棋子,游戏结束;如果无法放置棋子将对方的棋子变成自己的,游戏结束。

  分析:

  

  代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
#define SIZE 6 // 游戏区大小,必须为偶数
#define BLANK ' ' // 空白
#define COMP_C 'X' // 电脑字符
#define PLAYER_C 'O' // 玩家字符 void display(char board[][SIZE]); // 负责显示
int valid_moves(char board[][SIZE], bool moves[][SIZE], char player); // 计算所有走法
void make_move(char board[][SIZE], int row, int col, char player); // 落子后执行转换
void computer_move(char board[][SIZE], bool moves[][SIZE], char player); // 电脑落子
int get_score(char board[][SIZE],char player); // 计算分数
int best_move(char board[][SIZE],bool moves[][SIZE],char player); // 电脑走法 int main(void){
char board[SIZE][SIZE] = {}; // 存放字符
bool moves[SIZE][SIZE] = {false}; // 对应坐标点是否可放置棋子
int row = ;
int col = ;
char again = ;
int no_of_games = ;
int no_of_moves = ;
int invalid_moves = ; // 每走一步,将值设置为0,连续2子无效,结束游戏
int comp_score = ;
int user_score = ;
bool next_player = true;
char y = ;
int x = ;
char input[SIZE] = {}; printf("XXOO棋,你懂的...\n");
printf("玩家持O,电脑持X,只能在对方的棋子旁边放置自己的棋子\n"
"当棋子的横、竖、斜方向有自己的棋子,对方的棋子会变成自己的\n"
"你可以走第一步,然后与电脑轮流下棋\n"
"祝好运(别被电脑XX了),按回车开始游戏\n"
"玩法:输入横竖坐标,例如:2b\n");
scanf("%c",&again); do{ // 外层循环,初始化每一次游戏
next_player = !next_player; // 控制玩家和电脑轮流下棋
no_of_moves = ; /* 初始化 */
for( row = ; row < SIZE; row++){
for( col = ; col < SIZE; col++ ){
board[row][col] = BLANK;
}
}
int mid = SIZE / ;
board[mid - ][mid - ] = board[mid][mid] = PLAYER_C;
board[mid - ][mid] = board[mid][mid - ] = COMP_C;
do{ // 内层循环,电脑和玩家轮流
display(board);
if(next_player = !next_player){ // 玩家先走
if( valid_moves(board, moves, PLAYER_C) ){ /* 接收玩家输入,并判断是否可放置棋子 */
for( ; ; ){
printf("Please enter your move ( row column ):");
fgets(input, SIZE ,stdin); // 控制输入字符个数
fflush(stdin);
/* 只读取前2个非空字符 */
int cnt = ;
while( isspace(input[cnt]) )cnt++;
//printf("%s\n",input);
x = atoi(&input[cnt++]);
x--; // 行减1,转换为二维数组索引
//printf("%d\n",x);
while( isspace(input[cnt]) )cnt++;
y = tolower(input[cnt]);
y -= 'a'; // 列字母减a //printf("%c\n",y);
if( x >= && y >= && x < SIZE && y < SIZE && moves[x][y] ){
make_move(board,x,y,PLAYER_C);
no_of_moves++;
break;
}
else{
printf("Not a valid move,try again.\n");
}
}
}
else{
if( ++invalid_moves < ){
printf("You have to pass,press return");
scanf("%c",&again);
}
else{
printf("Neither of us can go, so the game is over.\n");
}
}
} /* 电脑下棋 */
else{
if( valid_moves(board,moves,COMP_C) ){
invalid_moves = ;
computer_move(board,moves,COMP_C);
no_of_moves++;
}
else{
if( ++invalid_moves < ){
printf("You have to pass,press return");
scanf("%c",&again);
}
else{
printf("Neither of us can go, so the game is over.\n");
}
}
}
}while( no_of_moves < SIZE * SIZE && invalid_moves < );
display(board);
comp_score = user_score = ;
for( row = ; row < SIZE; row++){
for( col = ; col < SIZE; col++ ){
comp_score += board[row][col] == COMP_C;
user_score += board[row][col] == PLAYER_C;
}
}
printf("The final score is:\n");
printf("Computer %d\nUser %d\n",comp_score,user_score);
printf("Do you want to play aiain (y/n):");
scanf(" %c",&again);
}while( 'y' == tolower(again) );
return ;
}
void display(char board[][SIZE]){
char col_label = 'a';
printf("\n ");
/* display the top line such as : a b c d e f .. */
for( int col = ; col < SIZE; col++ ){
printf(" %c", col_label + col);
}
printf("\n"); /* display the rows */
for( int row = ; row < SIZE; row++ ){
printf(" +");
for( int col = ; col < SIZE; col++ ){
printf("---+");
}
printf("\n%2d|", row + );
for( int col = ; col < SIZE; col++){
printf(" %c |", board[row][col]);
}
printf("\n");
}
printf(" +"); /* display the bottom */
for( int col = ; col < SIZE; col++ ){
printf("---+");
}
printf("\n");
}
/* **********************************************************
* 对每一空格搜寻周围8个格子(或者更少),是否有对手的棋子
* 如果有,沿着对手棋子的横、竖、斜方向查找自己的棋子;
* 找到则可以在此空格落子,否则设置为false
* **********************************************************/
int valid_moves(char board[][SIZE], bool moves[][SIZE], char player){
int rowdelta = ;
int coldelta = ;
int x = ;
int y = ;
int no_of_moves = ; char opponent = (player == PLAYER_C) ? COMP_C : PLAYER_C;
for( int row = ; row < SIZE; row++ ){
for( int col = ; col < SIZE; col++ ){
moves[row][col] = false;
}
}
for( int row = ; row < SIZE; row++ ){
for( int col = ; col < SIZE; col++ ){
if(board[row][col] != BLANK){
continue;
}
for( rowdelta = -; rowdelta <= ; rowdelta++ ){
for( coldelta = -; coldelta <= ; coldelta++ ){ /* 跳过越界的坐标和当前空格 */
if( row + rowdelta < || row + rowdelta >= SIZE ||
col + coldelta < || col + coldelta >= SIZE ||
( == rowdelta && == coldelta ) ){
continue;
}
/* 找到对手的棋子 */
if( opponent == board[row + rowdelta][col + coldelta] ){
x = row + rowdelta;
y = col + coldelta;
/* 沿着当前方向查找自己的棋子 */
for( ; ; ){
x += rowdelta;
y += coldelta;
if( x < || x >= SIZE || y < || y >= SIZE ){
break;
}
if( BLANK == board[x][y] ){
break;
}
if( player == board[x][y] ){
moves[row][col] = true;
no_of_moves++;
break;
}
}
}
}
}
}
}
return no_of_moves; // 返回值大于0说明该空格可以落子,否则不能
}
/* **********************************************************
* 搜寻周围8个格子(或者更少),是否有对手的棋子
* 如果有,沿着对手棋子的所在方向查找自己的棋子,
* 出界活在找到空格,跳出循环,在外层循环移动到下一个棋格。
* 如果找到自己的棋子,将该方向上对手的所有棋子变成自己的
* **********************************************************/
void make_move(char board[][SIZE], int row, int col, char player){
int rowdelta = ;
int coldelta = ;
int x = ;
int y = ;
char opponent = (player == PLAYER_C) ? COMP_C : PLAYER_C; board[row][col] = player;
for( rowdelta = -; rowdelta <= ; rowdelta++ ){
for( coldelta = -; coldelta <= ; coldelta++ ){
if( row + rowdelta < || row + rowdelta >= SIZE ||
col + coldelta < || col + coldelta >= SIZE ||
( == rowdelta && == coldelta ) ){
continue;
}
/* 找到了对手的棋子,沿此方向继续查找 */
if( opponent == board[row + rowdelta][col + coldelta] ){
x = row + rowdelta;
y = col + coldelta;
for( ; ; ){
x += rowdelta;
y += coldelta;
if( x < || x >= SIZE || y < || y >= SIZE ){
break;
}
if( BLANK == board[x][y] ){
break;
}
/* 找到自己的棋子 */
if( player == board[x][y] ){ /* 沿反方向将对手的棋子替换成自己的 */
while( opponent == board[x-=rowdelta][y-=coldelta] ){
board[x][y] = player;
}
break;
}
}
}
}
}
}
/* **********************************************************
* 计算电脑的所有可能走法,并判断玩家的可能走法,
* 选出使玩家分数最低的走法
* **********************************************************/
void computer_move(char board[][SIZE], bool moves[][SIZE], char player){
int best_row = ;
int best_col = ;
int new_score = ;
int score = ;
char temp_board[SIZE][SIZE];
bool temp_moves[SIZE][SIZE]; char opponent = (player == PLAYER_C) ? COMP_C : PLAYER_C;
for( int row = ; row < SIZE; row++ ){
for( int col = ; col < SIZE; col++ ){
if( !moves[row][col] ){
continue;
}
memcpy(temp_board,board,sizeof(temp_board)); // 创建副本
make_move(temp_board,row,col,player); // 模拟电脑走法
valid_moves(temp_board,temp_moves,opponent); // 计算玩家走法
new_score = best_move(temp_board,temp_moves,opponent); // 计算玩家得分
if( new_score < score ){
score = new_score;
best_row = row;
best_col = col;
}
}
}
make_move(board,best_row,best_col,player);
}
/* **********************************************************
* 计算得分,自己的棋子加1分,对手的棋子减1分
* **********************************************************/
int get_score(char board[][SIZE],char player){
int score = ;
char opponent = (player == PLAYER_C) ? COMP_C : PLAYER_C; for( int row = ; row < SIZE; row++ ){
for( int col = ; col < SIZE; col++ ){
score -= board[row][col] == opponent;
score += board[row][col] == player;
}
}
return score;
}
/* **********************************************************
* 返回玩家当前有效走法中得分最高的走法
* **********************************************************/
int best_move(char board[][SIZE],bool moves[][SIZE],char player){
//char opponent = (player == PLAYER_C) ? COMP_C : PLAYER_C;
char new_board[SIZE][SIZE] = {};
int score = ;
int new_score = ;
for( int row = ; row < SIZE; row++ ){
for( int col = ; col < SIZE; col++ ){
if( !moves[row][col] ){
continue;
}
memcpy(new_board,board,sizeof(new_board)); // 创建副本
make_move(new_board,row,col,player); // 模拟玩家可能走法
new_score = get_score(new_board,player); // 计算玩家得分
if( score < new_score ){
score = new_score;
}
}
}
return score;
}

  编译:

  gcc reversi.c -std=c99

C仿黑白棋版XO棋的更多相关文章

  1. 用Dart写的黑白棋游戏

    2013年11月,Dart语言1.0稳定版SDK发布,普天同庆.从此,网页编程不再纠结了. 在我看来,Dart语法简直就是C#的升级版,太像了.之所以喜欢Ruby的一个重要理由是支持mixin功能,而 ...

  2. js+canvas黑白棋

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. 51nod 1368:黑白棋 二分图最大匹配

    1368 黑白棋 题目来源: TopCoder 基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题  收藏  取消关注 有一个N*M的棋盘(1<=N,M< ...

  4. python3+tkinter实现的黑白棋,代码完整 100%能运行

    今天分享给大家的是采用Python3+tkinter制作而成的小项目--黑白棋 tkinter是Python内置的图形化模块,简单易用,一般的小型UI程序可以快速用它实现,具体的tkinter相关知识 ...

  5. Ubuntu 14 安装 “宋体,微软雅黑,WPS Office的symbol、wingdings、wingdings 2、wingdings 3、webding字体,Consolas雅黑混合版编程字体” 等 Windows 7 下的字体

    Windows平台下,“宋体”.“微软雅黑”.“Courier New(编程字体)”用的比较多,看的也习惯了.那如何在 Ubuntu下也安装这些字体呢? 操作步骤如下: 第一步:从 Windows 7 ...

  6. [CareerCup] 8.8 Othello Game 黑白棋游戏

    8.8 Othello is played as follows: Each Othello piece is white on one side and black on the other. Wh ...

  7. 黑白棋游戏 (codevs 2743)题解

    [问题描述] 黑白棋游戏的棋盘由4×4方格阵列构成.棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子.这16枚棋子的每一种放置方案都构成一个游戏状态.在棋盘上拥有1条公共边的2个方格称为相邻方 ...

  8. bzoj 2281 [Sdoi2011]黑白棋(博弈+组合计数)

    黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色 ...

  9. C#黑白棋制作~

    前些天自己复习一下C#语言 做了个黑白棋,望大家看一下,可能有些bug嘿嘿 链接如下 http://files.cnblogs.com/files/flyingjun/%E9%BB%91%E7%99% ...

随机推荐

  1. SpringMVC、SpringFox和Swagger整合项目实例

    目标 在做项目的时候,有时候需要提供其它平台(如业务平台)相关的HTTP接口,业务平台则通过开放的HTTP接口获取相关的内容,并完成自身业务~ 提供对外开放HTTP API接口,比较常用的是采用Spr ...

  2. HTML表格跨行、跨列操作(rowspan、colspan)

    转自:https://blog.csdn.net/u012724595/article/details/79401401 一般使用<td>元素的colspan属性来实现单元格跨列操作,使用 ...

  3. cscope安装

    安装 # apt-get install cscope .vimrc中添加 if has("cscope") set csprg=/usr/bin/cscope set csto= ...

  4. HDFS-SecondaryNameNode(SNN)角色介绍

    它出现在Hadoop1.x版本中,又称辅助NameNode,在Hadoop2.x以后的版本中此角色消失.如果充当datanode节点的一台机器宕机或者损害,其数据不会丢失,因为备份数据还存在于其他的d ...

  5. 用D3.js画树状图

    做项目遇到一个需求,将具有层级关系的词语用树状图的形式展示它们之间的关系,像这样: 或者是这样: 上面的图片只是样例,跟我下面的代码里面用的数据不同 网上有很多这种数据可视化展示的js控件,我这里选择 ...

  6. error 106: Can't Access ASP.NET\ClientFiles\

    Error 1606 Can’t access ASP.NET\ClientFiles\ when installing Crystal Reports Support Pack 10     Sea ...

  7. 浦发银行网上银行U盾证书无法更新的解决办法

    浦发银行需要更新证书.很多浦发客户都会碰到题主一样更新证书失败的困扰.网银登录似乎一切正常,可是等待进入个人网银时却跳出提示,如下图: 没有选择,只能点击确定,然后就是: 再“确定”下去: 再确定就出 ...

  8. 使用Cloudera Manager搭建Impala环境

    使用Cloudera Manager搭建Impala服务 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.使用CM安装Imapala 1>.进入CM的服务安装向导 2> ...

  9. linux系统编程之文件与io(一)

    经过了漫长的学习,C语言相关的的基础知识算是告一段落了,这也是尝试用写博客的形式来学习c语言,回过头来看,虽说可能写的内容有些比较简单,但是个人感觉是有史起来学习最踏实的一次,因为里面的每个实验都是自 ...

  10. Django之路——8 cookie 和sessions

    会话跟踪技术 1 什么是会话跟踪技术 我们需要先了解一下什么是会话!可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应.例如你给10086打个电话,你就是客户端,而10 ...