gpt4 book ai didi

c# - 为什么我会收到错误 "NullReferenceException was unhandled"?

转载 作者:太空宇宙 更新时间:2023-11-03 21:42:16 25 4
gpt4 key购买 nike

我正在尝试制作 slider 益智游戏,但在我的 form1 中调用 myBoard.paint(e.Graphics) 时,我不断收到错误“NullReferenceException 未处理”。请帮助我!!!

这是我的 Form1 代码(如果我需要发布一些其他类代码,请告诉我):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

namespace SliderPuzzle
{
public partial class Form1 : Form
{
private int tileSize;
private int rowsCols;
private SlidePuzzle myBoard;
private Stopwatch timer;
private int moveCount;

public Form1()
{
InitializeComponent();
pictureBox1.TabIndex = 3;
pictureBox1.Size = new Size(100, 50);
pictureBox1.Location = new Point(16, 71);
pictureBox1.BackColor = Color.PaleGreen;
pictureBox1.BorderStyle = BorderStyle.Fixed3D;
pictureBox1.TabStop = false;
tileSize = imageList1.ImageSize.Width;
rowsCols = 3;
pictureBox1.Width = rowsCols * tileSize;
pictureBox1.Height = rowsCols * tileSize;
}

public void initGame()
{
myBoard = new SlidePuzzle(rowsCols, tileSize, imageList1);
timer = new Stopwatch();
moveCount = 0;
timer.Start();
}

private void Form1_Load(object sender, EventArgs e)
{
initGame();
}

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
this.myBoard.paint(e.Graphics);
}

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (myBoard.move(e.Y / tileSize, e.X / tileSize))
++moveCount;
Refresh();
if (!myBoard.winner())
return;
timer.Stop();
if (MessageBox.Show(string.Format("You won!!\nIt took you {0} moves and {1:F2} seconds.\nPlay again?", (object)moveCount, (object)timer.Elapsed.TotalSeconds), "Game Over", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No)
{
Close();
}
else
{
initGame();
Refresh();
}
}
}
}

更新 #1:好的,所以我移动了 myBoard = new SlidePuzzle(rowsCols, tileSize, imageList1);给我的构造函数,但现在没有任何图像显示在上面。这是它的外观与它应该看起来的样子:enter image description here

编辑#2:好的,我把它移回原来的位置并放上

if (this.myBoard != null)
this.myBoard.paint(e.Graphics);

相反,它工作得更好,看起来也更好。但是图像不显示仍然是个问题。

编辑 #3:这是 SliderPuzzle.Paint 代码:

        public void paint(Graphics g)
{
for (int r = 0; r < this.myGrid.getNumRows(); ++r)
{
for (int c = 0; c < this.myGrid.getNumCols(); ++c)
this.myGrid.get(new Location(r, c)).paint(g);
}
}

编辑 #4:这是 SliderPuzzle 类的代码:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace SliderPuzzle
{
internal class SlidePuzzle
{
private static Random rand = new Random();
private int myTileSize;
private BoundedGrid myGrid;
private ImageList myImages;
private Location myBlankLoc;

static SlidePuzzle()
{
}

public SlidePuzzle(int rowsCols, int tileSize, ImageList images)
{
this.myTileSize = tileSize;
this.myGrid = new BoundedGrid(rowsCols, rowsCols);
this.myImages = images;
this.myBlankLoc = new Location(rowsCols - 1, rowsCols - 1);
this.initBoard();
}

private void initBoard()
{
int index1 = 0;
for (int r = 0; r < this.myGrid.getNumRows(); ++r)
{
for (int c = 0; c < this.myGrid.getNumCols(); ++c)
{
this.myGrid.put(new Location(r, c), new Tile(index1, this.myTileSize, new Location(r, c), this.myImages.Images[index1]));
++index1;
}
}
for (int index2 = 0; index2 < 1000; ++index2)
{
Location adjacentLocation = this.myBlankLoc.getAdjacentLocation(SlidePuzzle.rand.Next(4) * 90);
if (this.myGrid.isValid(adjacentLocation))
{
this.swap(this.myBlankLoc, adjacentLocation);
this.myBlankLoc = adjacentLocation;
}
}
}

public bool move(int row, int col)
{
Location loc1 = new Location(row, col);
if (Math.Abs(this.myBlankLoc.getRow() - row) + Math.Abs(this.myBlankLoc.getCol() - col) != 1)
return false;
this.swap(loc1, this.myBlankLoc);
this.myBlankLoc = loc1;
return true;
}

public bool winner()
{
int num = 0;
for (int r = 0; r < this.myGrid.getNumRows(); ++r)
{
for (int c = 0; c < this.myGrid.getNumCols(); ++c)
{
if (this.myGrid.get(new Location(r, c)).getValue() != num)
return false;
++num;
}
}
return true;
}

private void swap(Location loc1, Location loc2)
{
Tile tile1 = this.myGrid.put(loc2, this.myGrid.get(loc1));
Tile tile2 = this.myGrid.put(loc1, tile1);
tile1.setLocation(loc1);
tile2.setLocation(loc2);
}

public void paint(Graphics g)
{
for (int r = 0; r < this.myGrid.getNumRows(); ++r)
{
for (int c = 0; c < this.myGrid.getNumCols(); ++c)
this.myGrid.get(new Location(r, c)).paint(g);
}
}
}
}

更新 #5:这是 Tile 类:

using System.Drawing;

namespace SliderPuzzle
{
internal class Tile
{
private int myValue;
private int mySize;
private Location myLoc;
private Image myImage;

public Tile(int value, int tileSize, Location loc, Image img)
{
this.myValue = value;
this.mySize = tileSize;
this.myLoc = loc;
this.myImage = img;
}

public int getValue()
{
return this.myValue;
}

public void setLocation(Location newLoc)
{
this.myLoc = newLoc;
}

public void paint(Graphics g)
{
g.DrawImage(this.myImage, this.myLoc.getCol() * this.mySize, this.myLoc.getRow() * this.mySize);
}
}
}

编辑 #6:这是位置类:

namespace SliderPuzzle
{
internal class Location
{
public const int LEFT = -90;
public const int RIGHT = 90;
public const int HALF_LEFT = -45;
public const int HALF_RIGHT = 45;
public const int FULL_CIRCLE = 360;
public const int HALF_CIRCLE = 180;
public const int AHEAD = 0;
public const int NORTH = 0;
public const int NORTHEAST = 45;
public const int EAST = 90;
public const int SOUTHEAST = 135;
public const int SOUTH = 180;
public const int SOUTHWEST = 225;
public const int WEST = 270;
public const int NORTHWEST = 315;
private int row;
private int col;

public Location(int r, int c)
{
this.row = r;
this.col = c;
}

public int getRow()
{
return this.row;
}

public int getCol()
{
return this.col;
}

public Location getAdjacentLocation(int direction)
{
int num1 = (direction + 22) % 360;
if (num1 < 0)
num1 += 360;
int num2 = num1 / 45 * 45;
int num3 = 0;
int num4 = 0;
if (num2 == 90)
num3 = 1;
else if (num2 == 135)
{
num3 = 1;
num4 = 1;
}
else if (num2 == 180)
num4 = 1;
else if (num2 == 225)
{
num3 = -1;
num4 = 1;
}
else if (num2 == 270)
num3 = -1;
else if (num2 == 315)
{
num3 = -1;
num4 = -1;
}
else if (num2 == 0)
num4 = -1;
else if (num2 == 45)
{
num3 = 1;
num4 = -1;
}
return new Location(this.getRow() + num4, this.getCol() + num3);
}

public bool equals(Location other)
{
if (this.getRow() == other.getRow())
return this.getCol() == other.getCol();
else
return false;
}

public int hashCode()
{
return this.getRow() * 3737 + this.getCol();
}

public int compareTo(Location otherLoc)
{
if (this.getRow() < otherLoc.getRow())
return -1;
if (this.getRow() > otherLoc.getRow())
return 1;
if (this.getCol() < otherLoc.getCol())
return -1;
return this.getCol() > otherLoc.getCol() ? 1 : 0;
}

public string toString()
{
return "(" + (object)this.getRow() + ", " + (string)(object)this.getCol() + ")";
}
}
}

编辑 #7:这是最后一个类,BoundedGrid 类:

using System;
using System.Collections.Generic;

namespace SliderPuzzle
{
internal class BoundedGrid
{
private Tile[,] occupantArray;

public BoundedGrid(int rows, int cols)
{
this.occupantArray = new Tile[rows, cols];
}

public int getNumRows()
{
return this.occupantArray.GetLength(0);
}

public int getNumCols()
{
return this.occupantArray.GetLength(1);
}

public bool isValid(Location loc)
{
if (0 <= loc.getRow() && loc.getRow() < this.getNumRows() && 0 <= loc.getCol())
return loc.getCol() < this.getNumCols();
else
return false;
}

public List<Location> getOccupiedLocations()
{
List<Location> list = new List<Location>();
for (int r = 0; r < this.getNumRows(); ++r)
{
for (int c = 0; c < this.getNumCols(); ++c)
{
Location loc = new Location(r, c);
if (this.get(loc) != null)
list.Add(loc);
}
}
return list;
}

public Tile get(Location loc)
{
if (!this.isValid(loc))
throw new Exception("Location " + (object)loc + " is not valid");
else
return this.occupantArray[loc.getRow(), loc.getCol()];
}

public Tile put(Location loc, Tile obj)
{
if (!this.isValid(loc))
throw new Exception("Location " + (object)loc + " is not valid");
if (obj == null)
throw new NullReferenceException("obj == null");
Tile tile = this.get(loc);
this.occupantArray[loc.getRow(), loc.getCol()] = obj;
return tile;
}

public Tile remove(Location loc)
{
if (!this.isValid(loc))
throw new Exception("Location " + (object)loc + " is not valid");
Tile tile = this.get(loc);
this.occupantArray[loc.getRow(), loc.getCol()] = (Tile)null;
return tile;
}
}
}

编辑 #8:当我点击图片框时,程序崩溃并提示 timer.Stop();在 form1 中给我一个 NullReferenceException!!!

编辑 #9:好的,这很有效...我发现图像仍然没有显示,但我认为它们从未被放置在网格上。当我点击网格时(仍然没有图像)它说我赢了。这应该只在我将图 block 移动到正确的顺序后才会显示。知道发生了什么事吗?

编辑 #10:我的程序现在终于可以运行了!原来我在 form1 的构造函数中放错了地方,现在一切正常了!图像显示一切!多酷啊!!!

感谢大家的贡献,现在我的学校项目将取得好成绩!

最佳答案

这是让您头疼的问题之一。当您可以保证事件永远不会被乱序调用时,尝试确定事件的确切顺序是可以的。不幸的是,Paint 事件会在各种奇怪的时间触发,甚至可能在 Load 事件之前触发。

唯一真正的答案是从不依赖以特定顺序触发的事件。在尝试绘制之前,请始终检查您的 myBoard 对象是否有效:

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (this.myBoard != null)
this.myBoard.paint(e.Graphics);
}

是的,正如其他人指出的那样,最好尽快创建所有对象 - 例如在构造函数中,这毕竟是构造函数的用途。即使那样,您仍然可以通过构造函数中的操作触发事件,这会毁了您一整天。您的偶数处理程序应该在构造函数代码中设置得尽可能晚,以解决这个问题。

经验法则:

  • 如果您正在创建将在事件处理程序中使用的自定义对象,请始终尝试在构造函数中调用 InitializeComponent 之前创建并初始化它们。

  • 尽可能晚地连接你的事件处理程序,尤其是像 Paint 这样的事情 - 在你的构造函数完成之前它不会有用,所以在构造函数中最后做。

关于c# - 为什么我会收到错误 "NullReferenceException was unhandled"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18752435/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com