a very interesting game:
#include <stdlib.h> #include <stdio.h> #include <conio.h> //应用 getch() 函数 函数用途:从控制台读取一个字符,但不显示在屏幕上 #include <string.h> //定义棋盘大小 标准 15*15棋盘 #define MAXIMUS 15 //存储对局信息 二维数组 int p[MAXIMUS][MAXIMUS]; //输出缓冲器 纵横分别 15*2+1个字符图标 15*4+3个字符图标 //目的:1、显示方形光标 2、打印棋盘(单字符长宽不等) char buff[MAXIMUS*2+1][MAXIMUS*4+3]; //当前光标位置 int Cx,Cy; //当前走子的玩家,1代表黑,2代表白 int Now; //当前写入缓冲器的行数和列数位置 int wl,wp; //在棋盘中央显示的文字信息 char* showText; //回合数 int count; //修改过的字符串复制函数,会忽略末端的\0 char* Copy(char* strDest,const char* strSrc); //初始化一个对局函数 void Initialize();//Initialize:初始化 //获得棋盘中指定坐标交点位置的字符,通过制表符拼成棋盘 char* getStyle(int i,int j); //获得指定坐标交点位置左上格的样式,通过制表符来模拟光标的显示 //getCurse:获得图案 char* getCurse(int i,int j); //向缓冲器写入字符串 void write(char* c); //缓冲器写入位置提行 void ln(); //将缓冲器内容输出到屏幕 void Display(); //将整个棋盘算出并储存到缓冲器,然后调用Display函数显示出来 void Print(); //在当前光标位置走子,如果非空,则返回0表示失败 int Put(); //胜负检查,即判断当前走子位置有没有造成五连珠的情况 int Check(); //进行整个对局,返回赢家信息 int RunGame(); //主函数 int main() { //设置标题 system("title 简易五子棋 ——翻转课堂"); //设置窗口大小 system("mode con cols=63 lines=32"); /*设置颜色 *system("color 0A"); 其中color后面的0是背景色代号,A是前景色代号。各颜色代码如下: *0=黑色 1=蓝色 2=绿色 3=湖蓝色 4=红色 5=紫色 6=黄色 7=白色 8=灰色 9=淡蓝色 *A=淡绿色 B=淡浅绿色 C=淡红色 D=淡紫色 E=淡黄色 F=亮白色 */ system("color 72"); //循环执行游戏 while(1) { RunGame(); } } //修改过的字符串复制函数,会忽略末端的\0 主要考虑到Dispaly函数 char* Copy(char* strDest,const char* strSrc) { char* strDestCopy = strDest; while (*strSrc!='\0') { *strDest++=*strSrc++; } return strDestCopy; } //进行整个对局,返回赢家信息(虽然有用上) int RunGame() { //输入变量 int input; //赢家信息 int victor; //初始化对局 Initialize(); //开始无限回合的死循环,直到出现胜利跳出 while(1) { //打印棋盘 Print(); //等待键盘按下一个字符 //getch 从控制台读取一个字符,但不显示在屏幕上 input=getch(); //如果是ESC则退出程序,ESC的ASCLL码为27 if(input==27) { //正常退出 exit(0); } //如果是空格则开始走子 else if(input==0x20) { //如果走子成功则判断胜负 //put判断当前位置能否走子,即是否已经走过子 if(Put()) { victor=Check(); //轮换当前走子玩家,3-1=2,3-2=1 Now=3-Now; //对局数+1 count++; //如果黑方达到胜利,显示提示文字并等待一次按键,返回胜利信息 if(victor==1) { showText="黑方获得了胜利!"; //重新输出棋盘 且中间为showText文字 Print(); /*When reading a function key or an arrow key, *each function must be called twice; *the first call returns 0 or 0xE0, *and the second call returns the actual key code. */ if(getch()==0xE0) { getch(); } return Now; //并无实际意义,只是结束循环 } //如果白方达到胜利,显示提示文字并等待一次按键,返回胜利信息 else if(victor==2) { showText="白方获得了胜利!"; Display(); if(getch()==0xE0) { getch(); } return Now; } //如果回合数达到了棋盘总量,即棋盘充满,即为平局 else if(count==MAXIMUS*MAXIMUS) { showText="平局!"; Display(); if(getch()==0xE0) { getch(); } return 0; } } } //如果按下的是方向键,会填充两次输入,第一次为0xE0表示按下的是控制键 else if(input==0xE0) { //获得第二次输入信息 input=getch(); //判断方向键方向并移动光标位置 switch(input) { case 0x4B: Cx--; break; case 0x48: Cy--; break; case 0x4D: Cx++; break; case 0x50: Cy++; break; } //如果光标位置越界则移动到对侧 if(Cx<0)Cx=MAXIMUS-1; if(Cy<0)Cy=MAXIMUS-1; if(Cx>MAXIMUS-1)Cx=0; if(Cy>MAXIMUS-1)Cy=0; } } } //初始化一个对局函数 void Initialize() { //循环变量 int i,j; //重置显示信息 showText=""; //回合数归零 count=0; //重置对局数据 for(i=0;i<MAXIMUS;i++) { for(j=0;j<MAXIMUS;j++) { p[i][j]=0; //各处走子归零 } } //重置光标到中央 Cx=Cy=MAXIMUS/2; //重置当前为黑方 Now=1; } //获得棋盘中指定坐标交点位置的字符,通过制表符拼成棋盘 char* getStyle(int i,int j) { //1为黑子 if(p[i][j]==1) return "●"; //2为白子 else if(p[i][j]==2) return "○"; //以下为边缘棋盘样式 else if(i==0&&j==0) return "┏"; else if(i==MAXIMUS-1&&j==0) return "┓"; else if(i==MAXIMUS-1&&j==MAXIMUS-1) return "┛"; else if(i==0&&j==MAXIMUS-1) return "┗"; else if(i==0) return "┠"; else if(i==MAXIMUS-1) return "┨"; else if(j==0) return "┯"; else if(j==MAXIMUS-1) return "┷"; //中间的空位 return "┼"; } //获得指定坐标交点位置左上格的样式,通过制表符来模拟光标的显示 char* getCurse(int i,int j) { if(i==Cx) { if(j==Cy) return "┏"; else if (j==Cy+1) return "┗"; } else if(i==Cx+1) { if(j==Cy) return "┓"; else if (j==Cy+1) return "┛"; } //如果不在光标附近则为空 return " "; } //向缓冲器写入字符串 void write(char* c) { //字符串复制 (地址,地址),修改 wl、wp 处的字符为*c所指字符 strcpy(buff[wl]+wp,c); //移至下一列 通过ln函数移动至下一行 wp+=strlen(c); } //缓冲器写入位置 提行 void ln() { //行数+1 wl+=1; //列数归0 wp=0; } //将缓冲器内容输出到屏幕 void Display() { //循环变量,中间文字信息的长度 //showText 在RunGame函数里写出 int i,l=strlen(showText); //算出中间文字信息居中显示所在的横坐标位置 int Offset=MAXIMUS*2+2-l/2; //如果位置为奇数,则移动到偶数,避免混乱 if(Offset%2==1) { Offset--; } //讲中间文字信息复制到缓冲器 //由于 没有 \0 可以顺利输出缓冲期中showText后的其余字节 Copy(buff[MAXIMUS]+Offset,showText); //如果中间文字长度为半角奇数,则补上空格,避免混乱 if(l%2==1) { *(buff[MAXIMUS]+Offset+l)=0x20; //空格的ASCLL码 为16进制 0x20 } //清理屏幕,准备写入 system("cls"); //system("CLS")可以实现清屏操作。 //循环写入每一行 for(i=0;i<MAXIMUS*2+1;i++) { printf("%s",buff[i]); //buff[i] 在Print函数里写入 //写入完每一行需要换行 if(i<MAXIMUS*2) printf("\n"); } } //将整个棋盘算出并储存到缓冲器(即buff 二维字符数组,寄存各位置字符),然后调用Display函数显示出来 //Print 为 写入各位置buff字符 但并不输出 Display 显示 void Print() //Print 之后 Display { //循环变量 int i,j; wl=0; wp=0; //写入出交点左上角的字符,因为需要打印棋盘右下角,所以可以横纵各多一次循环 for(j=0;j<=MAXIMUS;j++) //第j行 j为行数 { for(i=0;i<=MAXIMUS;i++) //第i列 i为列数 { //写入左上角字符 write(getCurse(i,j)); //判断i,j是否在光标位置 如果不是 getCurse函数返回“ ”填充棋盘 //如果是棋盘上下边缘则没有连接的竖线,用空格填充位置 if(j==0||j==MAXIMUS) { if(i!=MAXIMUS) // != 暂无特殊含义 write(" "); //最上 最下 各空一行 } //如果在棋盘中间则用竖线承接上下 else { //左右边缘的竖线更粗 if(i==0||i==MAXIMUS-1) write("┃"); //中间的竖线 else if(i!=MAXIMUS) write("│"); } } //如果是最后一次循环,则只需要处理边侧字符,交点要少一排 if(j==MAXIMUS) { break; } //提行开始打印交点内容 ln(); //用空位补齐位置 左侧一列 补为空 write(" "); //按横坐标循环正常的次数 for(i=0;i<MAXIMUS;i++) { //写入交点字符 write(getStyle(i,j)); //如果不在最右侧则补充一个横线承接左右 if(i!=MAXIMUS-1) { if(j==0||j==MAXIMUS-1) { //上下边缘的横线更粗 write("━"); } else { //中间的横线 write("—"); } } } //写完一行后提行 ln(); } //将缓冲器内容输出到屏幕 Display(); } //在当前光标位置走子,如果非空,则返回0表示失败 int Put() { if(p[Cx][Cy]==0) { //改变该位置数据 p[Cx][Cy]=Now; //标记当前走子:走子位置写入1/2 //返回1表示成功 return 1; } else { return 0; } } //胜负检查,即判断当前走子位置有没有造成五连珠的情况 int Check() { //累计横竖正斜反斜四个方向的连续相同棋子数目 int w=1,x=1,y=1,z=1,i; //向下检查 for(i=1;i<5;i++)if(Cy+i<MAXIMUS&&p[Cx][Cy+i]==Now)w++;else break; //向上检查 for(i=1;i<5;i++)if(Cy-i>0&&p[Cx][Cy-i]==Now)w++;else break; //若果达到5个则判断当前走子玩家为赢家 if(w>=5)return Now; //向右检查 for(i=1;i<5;i++)if(Cx+i<MAXIMUS&&p[Cx+i][Cy]==Now)x++;else break; //向左检查 for(i=1;i<5;i++)if(Cx-i>0&&p[Cx-i][Cy]==Now)x++;else break; //若果达到5个则判断当前走子玩家为赢家 if(x>=5)return Now; //向右下检查 for(i=1;i<5;i++)if(Cx+i<MAXIMUS&&Cy+i<MAXIMUS&&p[Cx+i][Cy+i]==Now)y++;else break; //向左上检查 for(i=1;i<5;i++)if(Cx-i>0&&Cy-i>0&&p[Cx-i][Cy-i]==Now)y++;else break; //若果达到5个则判断当前走子玩家为赢家 if(y>=5)return Now; //向右上检查 for(i=1;i<5;i++)if(Cx+i<MAXIMUS&&Cy-i>0&&p[Cx+i][Cy-i]==Now)z++;else break; //向左下检查 for(i=1;i<5;i++)if(Cx-i>0&&Cy+i<MAXIMUS&&p[Cx-i][Cy+i]==Now)z++;else break; //若果达到5个则判断当前走子玩家为赢家 if(z>=5)return Now; //若没有检查到五连珠,则返回0表示还没有玩家达成胜利 return 0; }
十一月 | ||||||
---|---|---|---|---|---|---|
日 | 一 | 二 | 三 | 四 | 五 | 六 |
27 | 28 | 29 | 30 | 31 | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |