我在做五子棋程序的时候遇到这个问题:
我在FORM1上放了PictureBox然后在PictureBox上加载棋盘图片 然后用程序实现下棋
我是这样画棋子的:
Graphics g = Graphics.FromImage(this.pictureBox1.Image);
g.DrawImage(this.imageList1.Images[chess.ChessColor - 1],chess.Pos.X,chess.Pos.Y,35,35);
this.pictureBox1.Refresh();
我想实现悔棋 就必须把前一步的棋子擦除 可是这样画上去的图片怎样才能擦除呢?
我尝试了很多方法都失败了 大家指点我一下 非常感谢:)

解决方案 »

  1.   

    可以考虑用两个图片(一黑/一白)代替Graphics画,相信这会更漂亮些哪!再加上,"悔棋"操作,要存储双方走旗的所有布局本来就比较难控制,所以建议还是用图片.
    这样可以专注于旗游戏程序逻辑,不考虑画图等方面的情况
      

  2.   

    我用Graphics.DrawImage()方法也就是用图片显示了
    我也确实是用ImageList放了一黑一白存储
    后来我用每个棋子都用pictureBox来显示 但是棋子是圆的 PictureBox确实方的 即使我的图片背景色为透明 显示棋子的时候也会留有边角的白色部分 这是我否定这个方法的原因
    我原来是用pictureBox.CreateGraphics()方法配合ImageList.Draw()方法画棋子的 下棋,悔棋都实现的很成功 但是有个问题 就是当整个程序窗口最小化后再还原为正常窗口后 棋盘上的所有棋子就被"洗"掉了!所以我才采用上面"洗"不掉棋子的方法
    哎 现在悔棋想"洗"掉的时候又无能为力了...
      

  3.   

    不知道我理解的对不对阿,我的想法是在悔棋的时候把悔棋前的棋盘状态重绘以后再帖出来显示,换句话说也就是不是擦除而是重建!
    Graphics g = Graphics.FromImage(this.pictureBox1.Image); g.DrawImage(“悔棋前棋盘状态”);this.pictureBox1.Refresh();
      

  4.   

    呵呵谢谢大家参与
    上面两位的方法我都想过了
    但是具体到怎么保存要画棋子的地方还是重建整个棋盘 我都不知道有什么办法能够实现
    对于保存画棋子前的地方的方案 我是根本不知道有什么方法能保存某一指定的窗体图案
    而对于后者 重建整个棋盘的方案 我想到用栈mystack.Push(pictureBox1.Image);的方法在每次下其都保存一次悔棋前的棋盘 但是当我mystack.Pop()出保存的棋盘再拿它给pictureBox1.Image赋值的时候 却还原不回悔棋前的图案!
      

  5.   

    既然用了
    Graphics g = Graphics.FromImage(this.pictureBox1.Image); \
    g.DrawImage(xx);
    为什么还要给pictureBox1.Image属性赋值呢??
    如果盘面和棋子都是用绘图的方法绘出来的PictureBox的绘图表面绘制出来的话pictureBox1.Image的属性可以一直都为空啊!或者用棋盘图片作这个属性,每次绘图(下子也好,悔棋也好)都只是重绘全部的棋子也可以阿
      

  6.   

    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using System.Text;namespace WindowsApplication2
    {
    public class Form1 : System.Windows.Forms.Form
    {
    private System.Windows.Forms.PictureBox pictureBox1;
    private System.Windows.Forms.Button button1;
    private System.ComponentModel.Container components = null; public Form1()
    {
    InitializeComponent();
    } protected override void Dispose( bool disposing )
    {
    if( disposing )
    {
    if (components != null) 
    {
    components.Dispose();
    }
    }
    base.Dispose( disposing );
    } #region Windows フォーム デザイナで生成されたコード  private void InitializeComponent()
    {
    System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1));
    this.pictureBox1 = new System.Windows.Forms.PictureBox();
    this.button1 = new System.Windows.Forms.Button();
    this.SuspendLayout();
    // 
    // pictureBox1
    // 
    this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
    this.pictureBox1.Location = new System.Drawing.Point(0, 0);
    this.pictureBox1.Name = "pictureBox1";
    this.pictureBox1.Size = new System.Drawing.Size(544, 408);
    this.pictureBox1.TabIndex = 0;
    this.pictureBox1.TabStop = false;
    this.pictureBox1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseDown);
    // 
    // button1
    // 
    this.button1.Location = new System.Drawing.Point(168, 424);
    this.button1.Name = "button1";
    this.button1.TabIndex = 1;
    this.button1.Text = "Clean";
    this.button1.Click += new System.EventHandler(this.button1_Click);
    // 
    // Form1
    // 
    this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
    this.ClientSize = new System.Drawing.Size(544, 453);
    this.Controls.Add(this.button1);
    this.Controls.Add(this.pictureBox1);
    this.Name = "Form1";
    this.Text = "Form1";
    this.ResumeLayout(false); }
    #endregion [STAThread]
    static void Main() 
    {
    Application.Run(new Form1());
    } private void pictureBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
    {
    Image img=Image.FromFile("Black.bmp");
    Graphics g = Graphics.FromImage(this.pictureBox1.Image);
    g.DrawImage(img,e.X,e.Y,img.Width,img.Height);
    this.pictureBox1.Refresh();
    } private void button1_Click(object sender, System.EventArgs e)
    {
    Image img=Image.FromFile("Back.bmp");
    Graphics g = Graphics.FromImage(this.pictureBox1.Image);
    g.DrawImage(img,0,0,img.Width,img.Height);
    this.pictureBox1.Refresh();
    } }
    }
      

  7.   

    din1001(push()) 呵呵 我没明白你的意思 你的按钮事件是用来悔棋的吗 那我每一步棋都要保存在磁盘上啊?然后悔棋的时候把上一步棋读取吗?我真的没明白你的意思:)
    apollp(形影相吊) 的方法倒可以尝试一下:)
      

  8.   

    我以为"画"在pictureBox上的图像就成为了PictureBox.Image的一部分了 所以才有了保存画完的Image然后悔棋的时候通过赋值的想法"还原"回来
      

  9.   

    我看你的"重建"思想不错,要是我也这么实现.
    在一个数组中(或是别的什么),把所下的子记录下来,顺序也要记下.
    在OnPain事件中,根据数组中的记录情况重建棋盘,这种思想我在写
    俄罗斯方块游戏时,用过,可行,只是屏幕有闪烁的现像,估计用DX来
    写的话,会好一些.
      

  10.   

    to:majiaking5(majia)不好意思昨天下班得早,那个按钮事件是用来清除所有棋子用的,虽然不是悔棋不过我想只要能把盘面清除了,再把到你需要的那步的所有棋子重绘出来,因该可以搞定吧!肯定是要把每一步棋都保存下来的阿,又不是很复杂很大的数据,不然你怎么实现多步的悔棋或者复盘功能呢?to:bbdog(贝贝狗)闪烁的问题用双缓冲的方法倒是能很大的改善。就是先把要的东西在内存里边画好在帖出来到窗体或者PictureBox上。
      

  11.   

    我用了另外一个表保存每一步棋子的数据了然后用栈 完全可以实现多步悔棋 我很想不用重建的方法实现 这样绘制的效率会高很多呢 但是就是这问题中最最关键的一点:如何保存pictureBox.Image上的指定区域上的图像呢(比如我就想保存要悔的那步棋的原有图像)还有又如何清除指定区域刚画上去的图像呢? 难道C#中就没法实现吗?真的让我很困惑 只能让人画上去 却没法让人擦下来 ...