散分第二帖 极限编程20小时的游戏作品 欢迎大家来捧场解决思路

散分第二帖 极限编程20小时的游戏作品 欢迎大家来捧场游戏规则:5 X 5的方格中 有15只羊 3只狼每回合狼可以

散分第二帖 极限编程20小时的游戏作品 欢迎大家来捧场
游戏规则:
5 X 5的方格中 有15只羊 3只狼
每回合狼可以空一格吃羊 也可以移动一格 吃光羊获胜
羊只能移动一格 围住所有狼获胜

基本功能已实现 希望有时间感兴趣的朋友一起讨论羊的AI
给出新思路或完善AI的朋友至少有20分

可以参考我写的AI

C/C++ code
// Play.cpp : 定义应用程序的入口点。//#include "stdafx.h"#include "Play.h"#define MAX_LOADSTRING 100// 全局变量:HINSTANCE hInst;                                // 当前实例TCHAR szTitle[MAX_LOADSTRING];                    // 标题栏文本TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名//自定义全局变量MYGDI    g[18];//15只羊和3匹狼的图片int        i, n;//i为循环变量 n为选中之狼的编号POINT    p[18];//15只羊和3匹狼的坐标POINT    k[25];//关键点RECT    rect = {0, 0, 528, 550};int        cx, cy;//鼠标点击的坐标bool    isChoose = false;//是否选择了狼bool    isAction = true;//是否轮到狼行动static    TCHAR c[3];// 此代码模块中包含的函数的前向声明:ATOM                MyRegisterClass(HINSTANCE hInstance);BOOL                InitInstance(HINSTANCE, int);LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);void    CALLBACK    timerProc(HWND hWnd, UINT msg, UINT id, DWORD dwTime);bool                NoHit();//碰撞检测bool                NoBody(int a);//障碍检测bool                eat();//吃羊检测int                    Alive();//还有几只羊bool                SheepAction();//羊的行动bool                hold(int key);//是否已经占据该关键点bool                CanBeEat(int key);//判断移动后是否会被吃bool                UP(int key);//向上找羊bool                DOWN(int key);//向下找羊bool                LEFT(int key);//向左找羊bool                RIGHT(int key);//向右找羊bool                SaveTop(int key);//移动前上面是否安全bool                SaveBelow(int key);//移动前下面是否安全bool                SaveLeft(int key);//移动前左面是否安全bool                SaveRight(int key);//移动前右面是否安全bool                UPSAVE(int key);//移动后上面是否安全bool                DOWNSAVE(int key);//移动后下面是否安全bool                LEFTSAVE(int key);//移动后左面是否安全bool                RIGHTSAVE(int key);//移动后右面是否安全bool                WolfUp(int wolf);//判断狼的上方是否被围bool                WolfDown(int wolf);//判断狼的下方是否被围bool                WolfLeft(int wolf);//判断狼的左方是否被围bool                WolfRight(int wolf);//判断狼的右方是否被围int                    getPos(int key);//根据狼或羊的编号获得位置编号bool                WolfCanAction();//判断是否还有狼可以行动int APIENTRY _tWinMain(HINSTANCE hInstance,                       HINSTANCE hPrevInstance,                       LPTSTR    lpCmdLine,                       int       nCmdShow){    UNREFERENCED_PARAMETER(hPrevInstance);    UNREFERENCED_PARAMETER(lpCmdLine);    // TODO: 在此放置代码。    MSG msg;    HACCEL hAccelTable;    // 初始化全局字符串    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);    LoadString(hInstance, IDC_PLAY, szWindowClass, MAX_LOADSTRING);    MyRegisterClass(hInstance);    // 执行应用程序初始化:    if (!InitInstance (hInstance, nCmdShow))    {        return FALSE;    }    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PLAY));    // 主消息循环:    while (GetMessage(&msg, NULL, 0, 0))    {        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))        {            TranslateMessage(&msg);            DispatchMessage(&msg);        }    }    return (int) msg.wParam;}////  函数: MyRegisterClass()////  目的: 注册窗口类。////  注释:////    仅当希望//    此代码与添加到 Windows 95 中的“RegisterClassEx”//    函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要,//    这样应用程序就可以获得关联的//    “格式正确的”小图标。//ATOM MyRegisterClass(HINSTANCE hInstance){    WNDCLASSEX wcex;    wcex.cbSize = sizeof(WNDCLASSEX);    wcex.style            = CS_HREDRAW | CS_VREDRAW;    wcex.lpfnWndProc    = WndProc;    wcex.cbClsExtra        = 0;    wcex.cbWndExtra        = 0;    wcex.hInstance        = hInstance;    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PLAY));    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);    wcex.lpszMenuName    = NULL;//MAKEINTRESOURCE(IDC_PLAY);    wcex.lpszClassName    = szWindowClass;    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));    return RegisterClassEx(&wcex);}////   函数: InitInstance(HINSTANCE, int)////   目的: 保存实例句柄并创建主窗口////   注释:////        在此函数中,我们在全局变量中保存实例句柄并//        创建和显示主程序窗口。//BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){    HWND hWnd;    hInst = hInstance; // 将实例句柄存储在全局变量中    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,        CW_USEDEFAULT, 0, 528, 550, NULL, NULL, hInstance, NULL);    if (!hWnd)    {        return FALSE;    }    ShowWindow(hWnd, nCmdShow);    UpdateWindow(hWnd);    // 初始化自定义全局变量    for (i = 0; i<18; i++)    {        if (i<15)        {            g[i].getFile(hWnd, _T("Images/羊.bmp"));            p[i].x = i % 5 * 102 + 2;            p[i].y = i / 5 * 102 + 2;        }         else        {            g[i].getFile(hWnd, _T("Images/狼.bmp"));            p[i].x = i % 5 * 102 + 104;            p[i].y = 410;        }    }    // 初始化关键点    for (i = 0; i<25; i++)    {        k[i].x = i % 5 * 102 + 2;        k[i].y = i / 5 * 102 + 2;    }    return TRUE;}////  函数: WndProc(HWND, UINT, WPARAM, LPARAM)////  目的: 处理主窗口的消息。////  WM_COMMAND    - 处理应用程序菜单//  WM_PAINT    - 绘制主窗口//  WM_DESTROY    - 发送退出消息并返回////LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){    int wmId, wmEvent;    PAINTSTRUCT ps;    HDC hdc;    static DBBUFFER buf(GetDC(hWnd), 528, 550);    switch (message)    {    case WM_CREATE:        SetTimer(hWnd, 1, 66, timerProc);        break;    case WM_LBUTTONDOWN:        cx = LOWORD(lParam);        cy = HIWORD(lParam);        if (isChoose)        {            // 狼的移动            if (cx>p[n].x && cy>p[n].y-102 &&cx<p[n].x+100 && cy<p[n].y-2)            {                //MessageBox(0, _T("上一"), 0, 0);                if (NoHit())                {                    p[n].y -= 102;                    isChoose = false;                    isAction = false;                }            }            if (cx>p[n].x && cy>p[n].y+102 &&cx<p[n].x+100 && cy<p[n].y+202)            {                //MessageBox(0, _T("下一"), 0, 0);                if (NoHit())                {                    p[n].y += 102;                    isChoose = false;                    isAction = false;                }            }            if (cx>p[n].x-102 && cy>p[n].y &&cx<p[n].x-2 && cy<p[n].y+100)            {                //MessageBox(0, _T("左一"), 0, 0);                if (NoHit())                {                    p[n].x -= 102;                    isChoose = false;                    isAction = false;                }            }            if (cx>p[n].x+102 && cy>p[n].y &&cx<p[n].x+202 && cy<p[n].y+100)            {                //MessageBox(0, _T("右一"), 0, 0);                if (NoHit())                {                    p[n].x += 102;                    isChoose = false;                    isAction = false;                }            }            // 吃羊            if (cx>p[n].x && cy>p[n].y-204 &&cx<p[n].x+100 && cy<p[n].y-104)            {                //MessageBox(0, _T("吃上"), 0, 0);                if (NoBody(0))                {                    if (eat())                    {                        p[n].y -= 204;                        isChoose = false;                        isAction = false;                    }                }            }            if (cx>p[n].x && cy>p[n].y+204 &&cx<p[n].x+100 && cy<p[n].y+304)            {                //MessageBox(0, _T("吃下"), 0, 0);                if (NoBody(1))                {                    if (eat())                    {                        p[n].y += 204;                        isChoose = false;                        isAction = false;                    }                }            }            if (cx>p[n].x-204 && cy>p[n].y &&cx<p[n].x-104 && cy<p[n].y+100)            {                //MessageBox(0, _T("吃左"), 0, 0);                if (NoBody(2))                {                    if (eat())                    {                        p[n].x -= 204;                        isChoose = false;                        isAction = false;                    }                }            }            if (cx>p[n].x+204 && cy>p[n].y &&cx<p[n].x+304 && cy<p[n].y+100)            {                //MessageBox(0, _T("吃右"), 0, 0);                if (NoBody(3))                {                    if (eat())                    {                        p[n].x += 204;                        isChoose = false;                        isAction = false;                    }                }            }                    }         else        {            for (i = 15; i<18; i++)            {                if (cx>p[i].x && cy>p[i].y && cx<p[i].x+100 && cy<p[i].y+100)                {                    n = i;                    isChoose = true;                                        /*c[0] = '1';                    c[1] = n%10+'0';                    c[2] = '\0';                    MessageBox(0, c, 0, 0);*/                    break;                }            }        }        if(!isAction)        {            // 羊的AI待完善            if (Alive())            {                if(SheepAction())                {                    if (WolfCanAction())                    {                        isAction = true;                    }                    else                    {                        MessageBox(0, _T("以后别说自己是狼"), 0, 0);                        PostQuitMessage(0);                    }                }                else                {                    MessageBox(0, _T("最后的羊也走投无路了."), 0, 0);                    PostQuitMessage(0);                }            }             else            {                MessageBox(0, _T("狼吃饱了.羊死光了."), 0, 0);//有了[MessageBox(0, _T("最后的羊也走投无路了."), 0, 0);]这句后 就不会执行到这里了吧                PostQuitMessage(0);            }        }        break;    case WM_COMMAND:        wmId    = LOWORD(wParam);        wmEvent = HIWORD(wParam);        // 分析菜单选择:        switch (wmId)        {        case IDM_ABOUT:            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);            break;        case IDM_EXIT:            DestroyWindow(hWnd);            break;        default:            return DefWindowProc(hWnd, message, wParam, lParam);        }        break;    case WM_PAINT:        hdc = BeginPaint(hWnd, &ps);        // TODO: 在此添加任意绘图代码...        FillRect(buf, &rect, (HBRUSH)GetStockObject(/*WHITE_BRUSH*/BLACK_BRUSH));                for (i = 0; i<18; i++)g[i].draw(buf, p[i].x, p[i].y);        buf.flush();        EndPaint(hWnd, &ps);        break;    case WM_DESTROY:        KillTimer(hWnd, 1);        PostQuitMessage(0);        break;    default:        return DefWindowProc(hWnd, message, wParam, lParam);}return 0;}// “关于”框的消息处理程序。INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){    UNREFERENCED_PARAMETER(lParam);    switch (message)    {    case WM_INITDIALOG:        return (INT_PTR)TRUE;    case WM_COMMAND:        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)        {            EndDialog(hDlg, LOWORD(wParam));            return (INT_PTR)TRUE;        }        break;    }    return (INT_PTR)FALSE;}// 自定义定时器void CALLBACK timerProc(HWND hWnd, UINT msg, UINT id, DWORD dwTime){    InvalidateRect(hWnd, NULL, FALSE);} 



源码地址:http://blog.csdn.net/teatimel/article/details/6742603


[解决办法]
好长。。。
[解决办法]
支持下~~
有时间拜读下
[解决办法]
那一群else if貌似可以精简……
[解决办法]
先占位再细看
[解决办法]
好多else if……
[解决办法]
来支持了,给分哈
[解决办法]
膜拜...
[解决办法]
jfle
[解决办法]
先问下。。游戏怎么玩。。设定不完善呀。。
羊怎么围住狼。。羊围住狼就被吃了。。
只要3只狼保持在第2排或第4排的2、3、4格,就保持不败。
[解决办法]
探讨

先问下。。游戏怎么玩。。设定不完善呀。。
羊怎么围住狼。。羊围住狼就被吃了。。
只要3只狼保持在第2排或第4排的2、3、4格,就保持不败。

[解决办法]
MARK一下 不错的程序
[解决办法]
一片if,else if。。。mark
[解决办法]
很牛B了。呵呵~
[解决办法]
顶下,一起学习
[解决办法]
mark 之
[解决办法]
希望那些说if..else..可以精简的能给个精简的大体方法。我要学习一下
[解决办法]
截图,想看看截图。。
[解决办法]
顶下,一起学习
[解决办法]
C/C++ code
        if (cx>p[n].x && cy>p[n].y-102 &&cx<p[n].x+100 && cy<p[n].y-2)            {                //MessageBox(0, _T("上一"), 0, 0);                if (NoHit())                {                    p[n].y -= 102;                    isChoose = false;                    isAction = false;                }            }            if (cx>p[n].x && cy>p[n].y+102 &&cx<p[n].x+100 && cy<p[n].y+202)            {                //MessageBox(0, _T("下一"), 0, 0);                if (NoHit())                {                    p[n].y += 102;                    isChoose = false;                    isAction = false;                }            }            if (cx>p[n].x-102 && cy>p[n].y &&cx<p[n].x-2 && cy<p[n].y+100)            {                //MessageBox(0, _T("左一"), 0, 0);                if (NoHit())                {                    p[n].x -= 102;                    isChoose = false;                    isAction = false;                }            }
[解决办法]

[解决办法]

[解决办法]
先占个位,有空慢慢看看
------解决方案--------------------


不错,捧个场先
[解决办法]
为啥说这个是极限编程呢?你想说这个程序挑战了你的体能极限?
[解决办法]
mark
[解决办法]

[解决办法]
有分还有源码。。。谢谢了
[解决办法]
LZ可以编译出来个EXE玩下,代码太长,没去看
[解决办法]
好长,读完就很极限了...
[解决办法]
放入截图吧

[解决办法]
先支持一下
[解决办法]
这也行 楼主膜拜。。
[解决办法]
不懂。。。。
[解决办法]
支持!!!!!!!!!!
[解决办法]
mark 顺便求分
[解决办法]
天,要死人的!
[解决办法]
强人。。
无力。。
[解决办法]
强力,牛人
[解决办法]

[解决办法]
接分来了
[解决办法]
写的好强大
[解决办法]
虽然接触过游戏的,但都是建立在有代码的基础上。 把狼和羊的游戏转化成算法看看他们之间有什么联系。

[解决办法]
可以参考 “摩天大楼” 游戏试试。
[解决办法]
学习之
[解决办法]
楼主辛苦了
[解决办法]
新手 继续分 求满足!!
[解决办法]
支持一下。
[解决办法]
新手看不大懂,学习下先。
[解决办法]
kankan!!
[解决办法]
接分1
[解决办法]
顶~~~这样看很累,有源码吗??
[解决办法]

探讨
引用:
为啥说这个是极限编程呢?你想说这个程序挑战了你的体能极限?

自我感觉是在我精神状态非常好的情况下两天半的工作时间 8+8+4=20小时 内写的

[解决办法]
好长啊
[解决办法]
刚开始看错了,看成20分钟了,我再想,就是超代码20分钟也抄不完啊,细看是20小时!

很不错了
[解决办法]
太牛了
------解决方案--------------------


探讨
引用:
可以参考 “摩天大楼” 游戏试试。

小雅MM 给个游戏链接我看看

[解决办法]
想看看截图
[解决办法]
mark
[解决办法]
随便转转\(^o^)/~

[解决办法]
自绘,不知效果咋样,lz给个exe玩玩试试
[解决办法]
支持支持~!!!!
[解决办法]
ooooooooooooooooooooo, jfjfjf
[解决办法]
学习了。。。。。。。。。。谢谢楼主!
[解决办法]
好长的代码,看的我晕死了、、、接分最重要
[解决办法]
我要接分。。。。
[解决办法]
看来,我只有接分。
[解决办法]
新手学习中。。。。。。。。。。。。
[解决办法]
半夜赶来膜拜楼主。。。顺道接分
[解决办法]
jf。。。。。。
[解决办法]
我做过一个类似的游戏,给你提点建议.

1.使用位棋盘. 用两个int来表示狼盘和羊盘.如果(x,y)有狼,狼盘上的第x*6+y位就置1.
每行有一个未用的位用于越界检测,最高两位未用.
这样可以大大加快运算速度.这绝不存在够快了的情况,加快速度就能在合理的时间内进行更深的搜索,获得更高的棋力.

2.AI使用最大-最小搜索.高级点的再加上α-β剪枝,再高级点的加上MTD-f.再高级还可加入开局库,餐具库.什么遗传算法,神经网络,都可以整上.
最难的部分是局面评价函数,遗传算法,神经网络就是帮助你跟这个的.只需要写一个框架出来,他会帮你寻找合适的参数.
后面几条比较难了,我只做到了α-β剪枝.

3.使用线程.你不希望电脑长时间思考时界面失去响应吧?在单独的工作线程内计算.计算完后用消息发给界面线程.为了避免复杂的线程同步,在线程开始时传入所有的参数,其中包括一个窗口句柄,一个退出标志指针.线程计算时跟所有的界面线程内的参数无关.
线程的取消.用户要悔棋时,需要工作线程停止正在进行的计算.此时界面线程改变退出标志.工作线程在递归内通过指针检测退出标志,发现置位了就退出.

4.优化算法.用位棋盘,必然要进行指数跟对数的计算.指数就用1<<x,对数麻烦一点,可以参考我的帖子
http://topic.csdn.net/u/20110427/13/6f8371c6-897d-44a3-9da7-e6fd3b4de761.html
中的算法7.
还有位计数,可以参考我的帖子
http://topic.csdn.net/u/20110426/15/889bf7f1-409b-4f15-91df-1e21c5a14743.html
中的32位的算法.

暂时想起来这么多.搞定了这些,别的都是细枝末节,很容易了.

祝你进步!
[解决办法]
恩 编写脚本也差不多,原来编程都是相差不大,20小时太累了,而且前提编写的东西都用过才行,要不找资料都要1,2天。值得学习。
[解决办法]
82楼...
[解决办法]
来学习,顶一下。
[解决办法]
探讨
我做过一个类似的游戏,给你提点建议.

1.使用位棋盘. 用两个int来表示狼盘和羊盘.如果(x,y)有狼,狼盘上的第x*6+y位就置1.
每行有一个未用的位用于越界检测,最高两位未用.
这样可以大大加快运算速度.这绝不存在够快了的情况,加快速度就能在合理的时间内进行更深的搜索,获得更高的棋力.

2.AI使用最大-最小搜索.高级点的再加上α-β剪枝,再高级点的加上MTD-f.再高级还……

[解决办法]
果断支持。。。虽然没看完代码。。
[解决办法]
很强大!
[解决办法]
顶一下~ 学习了~~~~~
[解决办法]
探讨
刚开始看错了,看成20分钟了,我再想,就是超代码20分钟也抄不完啊,细看是20小时!

很不错了

------解决方案--------------------


顶一把,虽然没看完
[解决办法]
学习。
[解决办法]
学校了。。
[解决办法]
真是见识了!威武啊!
[解决办法]
我吧,我承认我是来接分的。
[解决办法]
hao 
!

[解决办法]
我吧,我承认我是来接分的。 


[解决办法]
顶上十分
[解决办法]
look
[解决办法]
顶上十分
[解决办法]
顶~~~这样看很累,有源码吗??
[解决办法]
学习,表示敬佩!