初学者:五子棋双人总结

我是个初学者

现在分享一下老师给我们讲的五子棋双人游戏总结

源代码部分及自己加的注释

/*
五子棋:棋盘上的3种状态:无棋子0,白棋1,红棋2。
*/

#include<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#include<bios.h>
#include<conio.h>

#define LEFT 0x4b00
#define RIGHT 0x4d00
#define DOWN 0x5000
#define UP 0x4800
#define ESC 0x011b
#define SPACE 0x3920

#define BILI 20
#define JZ 4
#define JS 3
#define N 19

int box[N][N];  /*定义二维数组*/
int step_x,step_y ;
int key ;
int flag=1 ;

void draw_box();  /**棋盘的初始化**/
void draw_cicle(int x,int y,int color);  /*画棋子:在judgewho中使用*/
void change();  /*改变棋子标记:在judgekey中使用*/
void judgewho(int x,int y);
void judgekey(); /* 与键盘结合:在main函数中使用*/
int judgeresult(int x,int y);   /*判断输赢的函数*/
void attentoin();   /*在main函数中使用*/

void attention()  /*初始界面,介绍游戏规则:在main函数中使用*/
{
    char ch ;
    window(1,1,80,25);
    textbackground(LIGHTBLUE);
    textcolor(YELLOW);
    clrscr();
    gotoxy(15,2);
    printf("游戏操作规则:");
    gotoxy(15,4);
    printf("Play Rules:");
    gotoxy(15,6);
    printf("1、按左右上下方向键移动棋子");
    gotoxy(15,8);
    printf("1. Press Left,Right,Up,Down Key to move Piece");
    gotoxy(15,10);
    printf("2、按空格确定落棋子");
    gotoxy(15,12);
    printf("2. Press Space to place the Piece");
    gotoxy(15,14);
    printf("3、禁止在棋盘外按空格");
    gotoxy(15,16);
    printf("3. DO NOT press Space outside of the chessboard");
    gotoxy(15,18);
    printf("你是否接受上述的游戏规则(Y/N)");
    gotoxy(15,20);
    printf("Do you accept the above Playing Rules? [Y/N]:");
    while(1)
    {
        gotoxy(60,20);
        ch=getche();  /*getche与getch的区别:
        getch:从控制台无回显地取一个字符,getche:从控制台取字符(带回显)*/
        /*如果同意按Y键进入游戏,不同意按N键退出游戏*/
        if(ch=='Y'||ch=='y')
        break ;
        else if(ch=='N'||ch=='n')
        {
         window(1,1,80,25);
      textbackground(BLACK);/*选择新的文本背景颜色 用 法: void textbackground(int color); */
      textcolor(LIGHTGRAY); /*在文本模式中选择新的字符颜色 用 法1.c语言类型: void textcolor(int color);*/
         clrscr();
         exit(0);
 }
        gotoxy(51,12);
        printf(" ");
    }
}
/*定义变量、背景色、当前屏幕的笔画颜色、划线line。
二维数组清零:用for循环实现的。*/
void draw_box()    /**棋盘的初始化函数**/
{
    int x1,x2,y1,y2 ;
    setbkcolor(LIGHTBLUE);/*功  能: 用调色板设置当前背景颜色 .用  法: void far setbkcolor(int color); */
    setcolor(YELLOW);  /*功  能: 设置当前画线颜色.用  法: void far setcolor(int color);*/
    gotoxy(7,2);
    printf("Left, Right, Up, Down KEY to move, Space to put, ESC-quit.");
    for(x1=1,y1=1,y2=18;x1<=18;x1++)
    line((x1+JZ)*BILI,(y1+JS)*BILI,(x1+JZ)*BILI,(y2+JS)*BILI); /*在指定两点间画一直线 : void far line(int x0, int y0, int x1, int y1);*/
    for(x1=1,y1=1,x2=18;y1<=18;y1++)
    line((x1+JZ)*BILI,(y1+JS)*BILI,(x2+JZ)*BILI,(y1+JS)*BILI);
    for(x1=1;x1<=18;x1++)  /*二维数组清零*/
    for(y1=1;y1<=18;y1++)
    box[x1][y1]=0 ;
}

void draw_circle(int x,int y,int color) /*画棋子:在judgewho中使用*/
{
    setcolor(color);
    setlinestyle(SOLID_LINE,0,1); /*设置当前画线宽度和类型 SOLID_LINE(实线)
    用 法: void far setlinestyle(int linestyle, unsigned pattern,int width);*/
    x=(x+JZ)*BILI ;
    y=(y+JS)*BILI ;
    /*功 能: 在给定半径以(x, y)为圆心画圆.用 法: void far circle(int x,int y,int radius);*/
    circle(x,y,8); /*以(x,y)为圆心,以8为半径画圆*/
}

void judgekey() /* 与键盘结合:在main函数中使用*/
{
    int i ;
    int j ;
    switch(key)
    {
    /*上下左右同理:如左*/
        case LEFT :      /*左*/

        if(step_x-1<0)   /*已经在最左端,无法移动*/
        break ;
        else
        {
            for(i=step_x-1,j=step_y;i>=1;i--) /*将step_x-1赋值给i,将step_y赋值给j,进行循环,判断是否能向左移动*/
            if(box[i][j]==0) /*如果要移动到的位置为0*/
            {
  draw_circle(step_x,step_y,LIGHTBLUE);  /*将原来的棋子地方画为背景色,以便于玩家看清棋子的移动*/
                break ;
            }
            if(i<1)break ;/*已经在最左端,无法移动*/
            step_x=i ;  /*将i赋值给step_x*/
            judgewho(step_x,step_y); /*画出当前位置的圆*/
            break ;
        }
        case RIGHT :       /*→*/

        if(step_x+1>18)
        break ;
        else
        {
            for(i=step_x+1,j=step_y;i<=18;i++)
            if(box[i][j]==0)
            {
  draw_circle(step_x,step_y,LIGHTBLUE);
                break ;
            }
            if(i>18)break ;
            step_x=i ;
            judgewho(step_x,step_y);
            break ;
        }
        case DOWN :          /*↓*/

        if((step_y+1)>18)
        break ;
        else
        {
            for(i=step_x,j=step_y+1;j<=18;j++)
            if(box[i][j]==0)
            {
  draw_circle(step_x,step_y,LIGHTBLUE);
                break ;
            }
            if(j>18)break ;
            step_y=j ;
            judgewho(step_x,step_y);
            break ;
        }
        case UP :         /*上*/

        if((step_y-1)<0)
        break ;
        else
        {
            for(i=step_x,j=step_y-1;j>=1;j--)
            if(box[i][j]==0)
            {
  draw_circle(step_x,step_y,LIGHTBLUE);
                break ;
            }
            if(j<1)break ;
            step_y=j ;
            judgewho(step_x,step_y);
            break ;
        }
        case ESC :      /*退出*/
        break ;

        case SPACE :     /*下子*/
        if(step_x>=1&&step_x<=18&&step_y>=1&&step_y<=18)  /*判断棋子是否在棋盘上*/
        {
            if(box[step_x][step_y]==0) /*如果当前位置数组元素值为0*/
            {
                box[step_x][step_y]=flag ; /*将当前元素赋值为flag值*/
                if(judgeresult(step_x,step_y)==1) /*调用judgeresult函数触发判断*/
                {
                    sound(1000);
                    delay(1000);
                    nosound();
                    gotoxy(30,4);
                    if(flag==1)    /*如果是是白棋*/
                    {
                        setbkcolor(BLUE);
                        cleardevice();  /*功 能: 清除图形屏幕,用 法: void far cleardevice(void); */
                        setviewport(100,100,540,380,1);
                        /*定义一个图形窗口*/
                        setfillstyle(1,2); /*设置填充模式和颜色*/
                        /*绿色以实填充*/
                        setcolor(YELLOW);
                        rectangle(0,0,439,279); /*画一个矩形*/
                        floodfill(50,50,14);    /*填充一个有界区域 */
                        setcolor(12);
                        settextstyle(1,0,5); /*功  能: 为图形输出设置当前的文本属性
                        用  法: void far settextstyle (int font, int direction, char size); */
                        /*三重笔划字体, 水平放大5倍*/
                        outtextxy(20,20,"The White Win !");
                        setcolor(15);
                        settextstyle(3,0,5);
                        /*无衬笔划字体, 水平放大5倍*/
                        outtextxy(120,120,"The White Win !");
                        setcolor(14);
                        settextstyle(2,0,8);
                        getch();
                        closegraph();
                        exit(0);
                    }
                    if(flag==2) /*如果是黑棋*/
                    {
                        setbkcolor(BLUE);
                        cleardevice();
                        setviewport(100,100,540,380,1);
                        /*定义一个图形窗口*/
                        setfillstyle(1,2);
                        /*绿色以实填充*/
                        setcolor(YELLOW);
                        rectangle(0,0,439,279);
                        floodfill(50,50,14);
                        setcolor(12);
                        settextstyle(1,0,8);
                        /*三重笔划字体, 水平放大8倍*/
                        outtextxy(20,20,"The Red Win !");
                        setcolor(15);
                        settextstyle(3,0,5);
                        /*无衬笔划字体, 水平放大5倍*/
                        outtextxy(120,120,"The Red Win !");
                        setcolor(14);
                        settextstyle(2,0,8);
                        getch();
                        closegraph();
                        exit(0);
                    }
                }
                change();/*棋子flag 1,2 变化的原理;当棋子下子成功后调用change函数,从而由一到二的改变*/
                break ;
            }
        }
        else
        break ;
    }
}

void change()    /*改变棋子的标记1,2。:在judgekey中使用*/
{
    if(flag==1)
    flag=2 ;
    else
    flag=1 ;
}

void judgewho(int x,int y)  /*根据标记1,2调用draw_circle函数画圆:在judgekey、main函数中使用*/
{
    if(flag==1)
    draw_circle(x,y,15); /*画白棋*/
    if(flag==2)
    draw_circle(x,y,4);  /*画红棋*/
}

int judgeresult(int x,int y)  /*判断输赢的函数*/
{
    int j,k,n1,n2 ;
    while(1)
    {   /*水平向左、水平向右为一组判断水平方向是否满足过关条件*/
        n1=0 ;
        n2=0 ;
        /*水平向左数*/
        for(j=x,k=y;j>=1;j--)
        {
            if(box[j][k]==flag)
            n1++;
            else
            break ;
        }
        /*水平向右数*/
        for(j=x,k=y;j<=18;j++)
        {
            if(box[j][k]==flag)
            n2++;
            else
            break ;
        }
        if(n1+n2-1>=5) /* 当满足水平方向或竖直方向或斜向连续白棋或红棋>=5个的时候过关*/
        {
            return(1);
            break ;
        }
        /*向上、向下为一组判断竖直方向是否满足过关条件*/
        /*垂直向上数*/
        n1=0 ;
        n2=0 ;
        for(j=x,k=y;k>=1;k--)
        {
            if(box[j][k]==flag)
            n1++;
            else
            break ;
        }
        /*垂直向下数*/
        for(j=x,k=y;k<=18;k++)
        {
            if(box[j][k]==flag)
            n2++;
            else
            break ;
        }
        if(n1+n2-1>=5) /* 当满足水平方向或竖直方向或斜向连续白棋或红棋>=5个的时候过关*/
        {
            return(1);
            break ;
        }
        /*向左上方、向右下方数为一组,判断斜向是否满足过关条件*/
        /*向左上方数*/
        n1=0 ;
        n2=0 ;
        for(j=x,k=y;j>=1,k>=1;j--,k--)
        {
            if(box[j][k]==flag)
            n1++;
            else
            break ;
        }
        /*向右下方数*/
        for(j=x,k=y;j<=18,k<=18;j++,k++)
        {
            if(box[j][k]==flag)
            n2++;
            else
            break ;
        }
        if(n1+n2-1>=5)  /* 当满足水平方向或竖直方向或斜向连续白棋或红棋>=5个的时候过关*/
        {
            return(1);
            break ;
        }
        /*右上方、向左下方为一组,判断斜向是否满足过关条件*/
        /*向右上方数*/
        n1=0 ;
        n2=0 ;
        for(j=x,k=y;j<=18,k>=1;j++,k--)
        {
            if(box[j][k]==flag)
            n1++;
            else
            break ;
        }
        /*向左下方数*/
        for(j=x,k=y;j>=1,k<=18;j--,k++)
        {
            if(box[j][k]==flag)
            n2++;
            else
            break ;
        }
        if(n1+n2-1>=5)  /* 当满足水平方向或竖直方向或斜向连续白棋或红棋>=5个的时候过关*/
        {
            return(1);
            break ;
        }
        return(0);
        break ;
    }
}
/*Main函数
首先定义了一些变量、清除文本模式窗口、调用attention函数。
定义flag=1,调用draw_box函数。
设计一个do,while循环:在循环中调用judgewho画圆函数并嵌套的do,while循环。
嵌套do,while循环中有while循环接收键盘输入信息,调用judgekey函数与键盘结合,判断移动,下子,退出的函数。*/
void main()
{
    int gdriver=VGA,gmode=VGAHI;
    clrscr();  /* 清除文本模式窗口*/
    attention(); /*调用函数*/
    registerbgidriver(EGAVGA_driver);  /* 注册BGI驱动后可以不需要.BGI文件的支持运行 */
    initgraph(&gdriver,&gmode,"c://tc");
    /* setwritemode(XOR_PUT);*/
    flag=1 ;
    draw_box(); /*划线等图形的初始化*/
    do
    {
        step_x=0 ; /*棋子的最初位置,选手下棋的最初位置,当前棋手的光标位置*/
        step_y=0 ;
        /*draw_circle(step_x,step_y,8); */
        judgewho(step_x-1,step_y-1); /*根据坐标和flag值调用画圆的函数画出棋手光 标位置*/
        do
        {
            while(bioskey(1)==0); /*不断接受键盘信息*/
            key=bioskey(0); /*将键盘接收的信息赋值给key*/
            judgekey(); /*与键盘结合,判断移动,下子,退出的函数*/
        }
        while(key!=SPACE&&key!=ESC);/*当按空格键和ESC键时退出do,while循环*/
    }
    while(key!=ESC);/*当按ESC键时退出do,while循环*/
    closegraph();/*关闭图形模式,回到文本模式*/
}

 

下面是一些思想总结

void main(){

    draw_box(); /*1.划线等图形的初始化 2.二维数组清零*/

    do /*dowhile循环:切换对手,即切换红白棋*/

    {

        step_x=0 ; /*棋子的最初位置,选手下棋的最初位置,当前棋手的光标位置*/

        step_y=0 ;

        judgewho(step_x-1,step_y-1); 

             /*根据坐标和flag值调用画圆的函数画出棋手光标位置*/

        do 

        {

            while(bioskey(1)==0); /*不断接受键盘信息*/

            key=bioskey(0); /*将键盘接收的信息赋值给key*/

            judgekey(); /*与键盘结合,判断移动,下子,退出的函数*/

        }

        while(key!=SPACE&&key!=ESC);/*当按空格键和ESC键时退出dowhile循环*/

    }

while(key!=ESC);/*当按ESC键时退出dowhile循环*/

}

 

void draw_box()    /**棋盘的初始化函数**/

{

    int x1,x2,y1,y2 ;

    setbkcolor(LIGHTBLUE);/*功  能用调色板设置当前背景颜色 .用  法: void far setbkcolor(int color); */

    setcolor(YELLOW);  /*功  能设置当前画线颜色.用  法: void far setcolor(int color);*/

    gotoxy(7,2);

    printf("Left, Right, Up, Down KEY to move, Space to put, ESC-quit.");

    for(x1=1,y1=1,y2=18;x1<=18;x1++)

    line((x1+JZ)*BILI,(y1+JS)*BILI,(x1+JZ)*BILI,(y2+JS)*BILI); /*在指定两点间画一直线 : void far line(int x0, int y0, int x1, int y1);*/

    for(x1=1,y1=1,x2=18;y1<=18;y1++)

    line((x1+JZ)*BILI,(y1+JS)*BILI,(x2+JZ)*BILI,(y1+JS)*BILI);

    for(x1=1;x1<=18;x1++)  /*二维数组清零*/

    for(y1=1;y1<=18;y1++)

    box[x1][y1]=0 ;

}

void judgewho(int x,int y)  /*根据标记12调用draw_circle函数画圆*/

{

    if(flag==1)

    draw_circle(x,y,15); /*画白棋*/

    if(flag==2)

    draw_circle(x,y,4);  /*画红棋*/

}

void draw_circle(int x,int y,int color) /*画棋子:即画圆*/

{

    setcolor(color);

    setlinestyle(SOLID_LINE,0,1); /*设置当前画线宽度和类型 SOLID_LINE(实线)

    用 法: void far setlinestyle(int linestyle, unsigned pattern,int width);*/

    x=(x+JZ)*BILI ;

    y=(y+JS)*BILI ;

    /*功 能在给定半径以(x, y)为圆心画圆.用 法: void far circle(int x,int y,int radius);*/

    circle(x,y,8); /*(x,y)为圆心,以8为半径画圆*/

}

void judgekey() /* 与键盘结合:在main函数中使用*/

{

    switch(key) /*得到键盘信息*/

    {

    /*上下左右同理:如左*/

        case LEFT :      /**/

         if(step_x-1<0)   /*已经是最左端无法移动*/

        break ;  /*退出*/

        else /*与最近的if配对及上一个*/

        {

            for(i=step_x-1,j=step_y;i>=1;i--) /*step_x-1赋值给i,将step_y赋值给j,进行循环,判断是否能向左移动*/

            /*能够向左移动执行*/

            if(box[i][j]==0) /*如果要移动到的位置为二维数组值为0*/

            {

            draw_circle(step_x,step_y,LIGHTBLUE); 

               /*将原来的棋子地方画为背景色,以便于玩家看清棋子的移动*/

                break ;

            }

            if(i<1)break ;/*如果最左端退出*/

            step_x=i ;  /*i赋值给step_x*/

            judgewho(step_x,step_y); /*画出当前位置的圆*/

            break ;

        }

        case ESC :      /*退出*/

        break ;

 

        case SPACE :     /*下子*/

        if(step_x>=1&&step_x<=18&&step_y>=1&&step_y<=18) 

          /*判断棋子是否在棋盘上*/

        {

            if(box[step_x][step_y]==0) /*如果当前位置二维数组值为0*/

            {

                box[step_x][step_y]=flag ; /*将当前二维数组赋值为flag*/

                if(judgeresult(step_x,step_y)==1/*调用judgeresult函数触发判断*/

                    /*如果不过关继续执行main函数最外层的dowhile循环*/

                {

                    /*当过关时,判断是1还是2,并输出相对应的信息*/

                    if(flag==1)    /*如果是是白棋*/

                    {   

                    }

                    if(flag==2)

                    {

                    }

                }

                change():/*棋子flag 1变化的原理;当按下空格键后调用change函数,从而由一到二的改变*/

                break ;

            }

        }

        else 

        break ;

    }

}

void change()    /*改变棋子的标记12:在judgekey中使用*/

{

    if(flag==1)

    flag=2 ;

    else 

    flag=1 ;

}

 

int judgeresult(int x,int y)  /*判断输赢的函数*/

{

    while(1) /*水平、竖直、斜向的判断方法相同*/

    {   /*水平向左、水平向右为一组判断水平方向是否满足过关条件*/

        n1=0 ;

        n2=0 ;

        /*水平向左数*/

        for(j=x,k=y;j>=1;j--)

        {

            if(box[j][k]==flag) /*水平向左有棋子时,n1++*/

            n1++;

            else 

            break ;

        }

        /*水平向右数*/

        for(j=x,k=y;j<=18;j++)/*水平向右有棋子时,n2++*/

        {

            if(box[j][k]==flag)

            n2++;

            else 

            break ;

        }

        if(n1+n2-1>=5) /* 当满足水平方向或竖直方向或斜向连续白棋或红棋>=5个的时候过关*/

        {

            return(1);  /*返回1,并推出*/

            break ;

        }

        return(0); /*当不过关时,返回0并退出*/

        break ;

    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值