Below I take a list and convert it to a data table and bind it to an ASP listview control.
I'd like a function to convert it back to a List from an asp listview control and cannot figure out how to get the items? In Visual Studio debugging, the dataitems are null? It has the proper count but no values? I'd like to enumerate through all rows.
private void createLvwTable(List<string> table)
{
int index = 0;
DataTable dt = new DataTable();
foreach (string row in table)
{
string[] cells = row.Split('|');
if (index == 0) // header column
{
for (int j = 0; j < cells.Length; j++)
{
dt.Columns.Add(cells[j]);
//dt.Rows.Add();
}
}
else
{
DataRow dr = dt.NewRow();
for (int j = 0; j < cells.Length; j++)
{
dr[j] = cells[j];
}
dt.Rows.Add(dr);
}
index++;
}
lvwOutput.DataSource = dt;
lvwOutput.DataBind();
}
This is idiotic IMO so there is most likely a better way, but it appears you have to bind the data to an object during the listview creation. I couldn't find a good answer anywhere, this is a compilation of hours of searching and trying different combinations of semi-related answers.
On the html side you have to set the 'onitemdatabound' to a c# function. The code below also does not need to have the segmentation I'm going with a "|", I left that in to make it easier to read if you copy/paste my function.
I'd be happy to still read replies on how to do this better so I can learn.
html:
<asp:ListView ID="lvwOutput" runat="server" onitemdatabound="lvwOutput_ItemDataBound">
asp:
private List<string> lvwOutputItemsDataBoundToList = new List<string>();
private List<string> lvwOutputItemsDataBoundToListOriginal = new List<string>();
protected void lvwOutput_ItemDataBoundToList(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
ListViewDataItem dataItem = (ListViewDataItem)e.Item;
object o = (object)dataItem.DataItem;
System.Data.DataRowView rowView = e.Item.DataItem as System.Data.DataRowView;
object[] itemArray = rowView.Row.ItemArray;
string itemBound = "";
foreach(object item in itemArray)
{
itemBound += item.ToString() + "|";
}
if (itemBound.EndsWith("||"))
{
int index = itemBound.Length;
itemBound = itemBound.Remove(index - 2);
}
if (itemBound.EndsWith("|"))
{
int index = itemBound.Length;
itemBound = itemBound.Remove(index - 1);
}
lvwOutputItemsDataBoundToList.Add(itemBound);
}
ViewState["lvwOutputItemsDataBoundToList"] = lvwOutputItemsDataBoundToList;
}
private void filter()
{
lvwOutputItemsDataBoundToList = (List<string>)ViewState["lvwOutputItemsDataBoundToList"];
lvwOutputItemsDataBoundToListOriginal = lvwOutputItemsDataBoundToList;
foreach (string item in lvwOutputItemsDataBoundToList)
{
string[] itemSplit = item.Split('|');
}
}
To enumerate the ListViewItems see ListView.ListViewItemCollection Class and ListViewItem.SubItems Property.
List<string> lstItems = new List<string>():
foreach(ListViewItem itemRow in lvwOutput)
{
for (int i = 0; i < itemRow.SubItems.Count; i++)
{
lstItems.Add(itemRow.SubItems[i].Text);
}
}
Related
Here I'm trying to write a code that can write and create a JSON File for me with the data I provide like row, column and depth.
For example, I need to spawn a 10 x 10 x 10 cube. And I give this data in unity Inspector also in the code when I'm serializing it.
I tried achieving this in a for loop and writing the JSON file. But I'm not getting the output I wanted. I am expecting output where the cube locations are different and in place what happens instead is all the data or cube position in my data is the one before the number I give. that is if I gave my row, column, and depth to be 10. So my data is like x: 9, y: 9, z:9 for the whole 1000 elements.Better explained in image down below.I know I'm doing a mistake at some point just not able to figure out where. Thanks for the help in Advance
public class JSONWriter : MonoBehaviour
{
[SerializeField] int rows , columns, depth = 10;
[SerializeField] float padding;
public enum CubeType
{
white,
yellow,
blue,
red,
green
}
private readonly IReadOnlyDictionary<CubeType, Color> colors = new Dictionary<CubeType, Color>
{
{CubeType.white, Color.white},
{CubeType.yellow, Color.yellow},
{CubeType.blue, Color.blue},
{CubeType.red, Color.red},
{CubeType.green, Color.green}
};
[System.Serializable]
public class CubeData
{
public Vector3 cubePosition;
public CubeType Cube;
}
[System.Serializable]
public class CubeDataList
{
public CubeData[] cubeDatas;
}
public void outputJSON()
{
string strOutput = JsonUtility.ToJson(myCubeDataList);
File.WriteAllText(Application.dataPath + "/Resources/10x10x10.txt", strOutput);
}
//CubeData myCubeData = new CubeData();
public CubeDataList myCubeDataList = new CubeDataList();
void Start()
{
for (int x = 0; x < myCubeDataList.cubeDatas.Length; x++)
{
//Debug.Log(myCubeDataList.cubeDatas.Length);
for (int i = 0; i < depth; i++)
{
for (int j = 0; j < columns; j++)
{
for (int k = 0; k < rows; k++)
{
myCubeDataList.cubeDatas[x].cubePosition = new Vector3(i, j, k) * padding;
//myCubeDataList.cubeDatas[x].Cube = Random.Range(CubeType, 3f);
}
}
}
}
}
}
You do not want to go through all i, j, k for each and every element x!
What you are doing is basically overwriting each and every element with the values for i=9, j=9, k=9.
Instead of an array I would rather simply use a dynamic List like
[Serializable]
public class CubeDataList
{
public List<CubeData> cubeDatas;
}
and then dynamically add them via
myCubeDataList.cubeDatas = new List<CubeData>(i * j * k);
for (int i = 0; i < depth; i++)
{
for (int j = 0; j < columns; j++)
{
for (int k = 0; k < rows; k++)
{
var data = new CubeData();
data.cubePosition = new Vector3(i, j, k) * padding;
data.Cube = Random.Range(CubeType, 3f);
myCubeDataList.cubeDatas.Add(data);
}
}
}
Or if you really want to go with an array
for (int i = 0; i < depth; i++)
{
for (int j = 0; j < columns; j++)
{
for (int k = 0; k < rows; k++)
{
var data = new CubeData();
myCubeDataList.cubeDatas[x].cubePosition = new Vector3(i, j, k) * padding;
myCubeDataList.cubeDatas[x].Cube = Random.Range(CubeType, 3f);
x++;
}
}
}
Though, from your previous question I know you actually do not want to fill the cube completely!
You actually only want the external shape (like a wall) and leave the cube empty on the inside.
So what you actually want would probably rather be
myCubeDataList.cubeDatas = new List<CubeData>(i * j * k);
for (int i = 0; i < depth; i++)
{
for (int j = 0; j < columns; j++)
{
for (int k = 0; k < rows; k++)
{
if(i == 0 || i == depth - 1
|| j == 0 || j == depth - 1
|| k == 0 || k == depth - 1)
{
var data = new CubeData();
data.cubePosition = new Vector3(i, j, k) * padding;
// TODO random enum (see below)
myCubeDataList.cubeDatas.Add(data);
}
}
}
}
For the random enum vlaue see e.g. this answer and do
private Random random = new Random();
and then where it says // TODO insert
var values = Enum.GetValues(typeof(Bar));
data.Cube = (CubeType)values.GetValue(random.Next(values.Length));
This is my quadtree class, but i haven't added the collision detection yet, in all the examples online they can get 500 + at 60 fps with collision detection but my one only running at 20 fps without collision detection.
I'm following this tutorial http://gamedevelopment.tutsplus.com/tutorials/quick-tip-use-quadtrees-to-detect-likely-collisions-in-2d-space--gamedev-374 which is java but im using as3
public class Quadtree extends Entity
{
private var Max_objects:int = 1;
private var Max_levels:int = 5;
private var level:int;
private var objects:Vector.<Rectangle>;
public var rectangle:Rectangle;
public var Quadtree_list:Vector.<Quadtree>;
public function Quadtree(tmp_level:int , tmp_rec:Rectangle)
{
level = tmp_level;
objects = new Vector.<Rectangle>();
rectangle = tmp_rec;
Quadtree_list = new Vector.<Quadtree>();
Quadtree_list.length = 3;
}
public function clear():void
{
objects.length = 0;
for (var i:Number = 0; i < Quadtree_list.length ; i++)
{
if (Quadtree_list[i] != null)
{
Quadtree_list[i].clear();
world.remove(Quadtree_list[i]);
Quadtree_list[i] = null;
}
}
}
public function split():void
{
var subWidth:int = rectangle.width / 2;
var subHeight:int = rectangle.height / 2;
var xx:int = rectangle.x;
var yy:int = rectangle.y;
Base._world.add(Quadtree_list[0] = new Quadtree(level + 1, new Rectangle(xx + subWidth, yy, subWidth, subHeight)));
Base._world.add(Quadtree_list[1] = new Quadtree(level+1,new Rectangle(xx ,yy,subWidth,subHeight)));
Base._world.add(Quadtree_list[2] = new Quadtree(level+1,new Rectangle(xx,yy + subHeight,subWidth,subHeight)));
Base._world.add(Quadtree_list[3] = new Quadtree(level+1,new Rectangle(xx + subWidth,yy + subHeight,subWidth,subHeight)));
}
/*
* Determine which node the object belongs to. -1 means
* object cannot completely fit within a child node and is part
* of the parent node
*/
public function get_index(tmp_rect:Rectangle):Number
{
var index:int = -1;
var verticalMidpoint:Number = rectangle.x + (rectangle.width / 2);
var horizontalMidpoint:Number = rectangle.y + (rectangle.height / 2);
// Object can completely fit within the top quadrants
var topQuadrant:Boolean = (tmp_rect.y < horizontalMidpoint && tmp_rect.y + tmp_rect.height < horizontalMidpoint);
// Object can completely fit within the bottom quadrants
var bottomQuadrant:Boolean = (tmp_rect.y > horizontalMidpoint);
// Object can completely fit within the left quadrants
if (tmp_rect.x < verticalMidpoint && tmp_rect.x + tmp_rect.width < verticalMidpoint)
{
if (topQuadrant)
{
index = 1;
}
else if (bottomQuadrant)
{
index = 2;
}
}
else
// Object can completely fit within the right quadrants
if (tmp_rect.x > verticalMidpoint)
{
if (topQuadrant)
{
index = 0;
}
else if (bottomQuadrant)
{
index = 3;
}
}
return index;
}
/*
* Insert the object into the quadtree. If the node
* exceeds the capacity, it will split and add all
* objects to their corresponding nodes.
*/
public function insert(tmp_rect:Rectangle):void
{
if (Quadtree_list[0] != null)
{
var index:int = get_index(tmp_rect);
if (index != -1)
{
Quadtree_list[index].insert(tmp_rect)
return;
}
}
objects.push(tmp_rect);
if (objects.length > Max_objects && level < Max_levels)
{
if (Quadtree_list[0] == null)
{
split();
}
var i:int = 0;
while (i < objects.length)
{
var indexx:int = get_index(objects[i]);
if (indexx != -1)
{
Quadtree_list[indexx].insert(objects[i]);
objects.splice(i, 1);
}
else
{
i++;
}
}
}
}
Can you see why it's not performing very well?
Hard to say for certain without seeing exactly how you're using it. Plus it extends Entity which could be doing ...anything :)
I'm not an expert on Quadtrees either, but if you're calling split() a lot, it looks like it could end up being taxing - lots of instantiation calls to new Quadtree and new Rectangle. If this is indeed a bottleneck, you could look into instantiating one rectangle instance that you just pass around. Same with Quadtree. Or use object pooling so you're at least recycling instead of creating new things like crazy.
I hope that helps :)
txt file containing urls that need to be open and display the contents in a 4x4 board in an html file. Having some trouble with this as I am new too html. the first board reads the words and the second is supposed to display the pictures in a randomized order.
this is the .text file
A,ant
B,bear
C,cat
D,dog
E,elephant
F,fox
G,goat
H,horse
I, iguana
J, Jaguar
K,kangaroo
L, lion
M,monkey
N,newt
O,ostrich
P,penguin
A,http://a-z-animals.com/media/animals/images/470x370/ant8.jpg
B,http://a-z-animals.com/media/animals/images/470x370/bear5.jpg
C,http://a-z-animals.com/media/animals/images/470x370/cat1.jpg
D, http://a-z-animals.com/media/animals/images/470x370/dog5.jpg
E, http://a-z-animals.com/media/animals/images/470x370/african_elephant.jpg
F, http://a-z-animals.com/media/animals/images/470x370/fox.jpg
G,goat, http://a-z-animals.com/media/animals/images/470x370/goat.jpg
H, http://a-z-animals.com/media/animals/images/470x370/horse8.jpg
I, http://www.vivanatura.org/Iguana_iguana_juv1.jpg
J, http://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Jaguar.jpg/800px-Jaguar.jpg
K,http://images.nationalgeographic.com/wpf/media-live/photos/000/005/cache/gray-kangaroo_554_600x450.jpg
L, http://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Lion_waiting_in_Namibia.jpg/800px-Lion_waiting_in_Namibia.jpg
M,http://upload.wikimedia.org/wikipedia/commons/d/d7/Crab-eating_Macaque_tree.jpg http://upload.wikimedia.org/wikipedia/commons/4/49/Notophthalmus_viridescensPCCA20040816-3983A.jpg
O,http://upload.wikimedia.org/wikipedia/commons/9/92/Ostriches_cape_point_cropped.jpg
P,http://upload.wikimedia.org/wikipedia/commons/b/be/Pygoscelis_papua.jpg
heres what i have so far, any hep would be much appreciated.
/*Muhammed Motala
* ics 240 prof. Jasthi
* THis program reads lines from a pre-existing text files and writes the
* contents to an HTMl file, while putting each line of code into a box forming two 4x4 board's.
*/
import java.io.*;
import java.util.*;
import javax.swing.*;
public class TicTacTwice {
public static void main (String [] args) throws IOException {
Scanner sc = new Scanner(new File("/Users/Muhammed/Documents/Tic_Tac_Twice/tic_tac_twice2.txt"));
BufferedWriter output = null;
String myLine = null;
String [] words = new String[100];
int counter = 0;
int counter1 = 0;
boolean run = true;
do {
try {
while(sc.hasNextLine()) { //reads each line in the txt file
String product = sc.nextLine();
myLine = product;
if (product.contains(" ")) { // if the line contains a space
String[] array1 = product.split(" "); // if contains space add to array
words[counter] = array1[1];
counter++;
}
if (product.contains("http://")) {
String [] array1 = product.split(",");
words[counter] = array1[1];
counter++;
System.out.println(array1[1]);
}
else if (product.contains(",")) { // if contains comma split into separate array
String [] array1 = product.split(",");
words[counter] = array1[1];
counter++;
}
}
sc.close();
FileWriter fw = new FileWriter("/Users/Muhammed/Documents/tic_tac_twice.html");
BufferedWriter bw = new BufferedWriter(fw);
bw.write("<html"); // html code upon writing of the file
bw.write("<head>");
bw.write("<table>");
bw.write("<h1> TICK TAC TWICE <h1>");
bw.write("<h1> Board 1 <h1>");
bw.write("</table>");
bw.write("</head>");
bw.write("<body>");
bw.write("<style>table, th, td{border:1px solid black;padding:5px}"
+ "table{border-spacing:15px}</style>");
bw.write("<table style=width:300px>");
for (int i = 0; i < 4; i++) { // array to create board1 and
// populate with the read in lines
bw.write("<tr>");
for (int j = 0; j < 4; j++) {
bw.write("<td>");
bw.write(words[counter1]);
counter1++;
bw.write("</td>");
}
bw.write("<tr>");
}
bw.write("<style>table, th, td{border:1px solid black;padding:5px}"
+ "table{border-spacing:15px}</style>");
bw.write("<table style=width:300px>");
for (int i = 0; i < 4; i++) { // creates board 2 and populates with
// words that are stored in array
bw.write("<tr>");
for (int j = 0; j < 4; j++) {
bw.write("<td>");
bw.write(words[counter1]);
bw.write("<td><img src=\"" + words[counter] +
"\" alt=\"some_text\"width=200 height=200></img>");
counter1++;
bw.write("</td>");
}
bw.write("<tr>");
}
bw.write("<h1> Board 2 <h1>");
bw.write("</body>");
bw.write("</html>");
bw.close();
run = false;
}
catch (Exception e) { // exception handler
System.out.print(e.toString());
}
}
while(run);
}
}
while passing list to json object i am not able to read all the elemnts.. it shows only the list which i stored very last
List<String> list = new ArrayList<String>();
for (int i=0 ; i<columnCount ; i++)
{
while (rs.next())
{
list.add(rs.getString(rsMetaData.getColumnName(i+1)));
}
json.put(rsMetaData.getColumnName(i+1), list);
//json.accumulate(rsMetaData.getColumnName(i+1), list);
}
ResultSet is a iterator who is iterated only once, for the first column.
The List-Object is only created once and strored multiple to json. Even if you store the list for the first column, you change this first-column value in the second column.
Try this:
while (rs.next()) {
for (int i=0; i < columnCount; i++) {
String columnName = rsMetaData.getColumnName(i+1);
List<String> list = new ArrayList<String>();
if (json.get(columnName) == null) {
json.put(columnName, list);
} else {
list = (List<String>)json.get(columnName);
}
list.add(rs.getString(columnName));
}
}
BTW: Duplicate columnNames are not supported by json
Finally i got the answer ...this is my code
try
{ HashMap map= new HashMap();
List list = new ArrayList();
int col = 0;
while (rs.next())
{
values = new JSONObject();
for (int i=0 ; i<columnCount ; i++)
{
values.put(rsMetaData.getColumnName(i+1),rs.getString(rsMetaData.getColumnName(i+1)));
}
list.add(col, values.toString());
System.out.println(list.toString());
col++;
}
json.put("gaea", list);
}//try block end
I am writing a match three engine and I succeed in creating the matching with using huge loops to find the matching items. Any ideas on how to fill the empty spaces with the items ( dropping down into the empty spaces ) and creating new items without excessive looping and if statements?
Here is my relavant code so far.
public var rows:uint = 8;
public var cols:uint = 7;
public var cell:Array = new Array();
public var plot:Array = new Array();
public var height:int;
public var width:int;
public var relativePositions:Array = [{name:'top', position:-1}, {name:'bottom', position:1}, {name:'left', position:rows*-1}, {name:'right', position:rows*1}];
public var dictionary:Dictionary = new Dictionary();
public var matches:Array = new Array();
public function createGrid(target:*, displayObject:*, spacer:int) : void {
var iterator:uint = 0;
for(var c:uint = 0;c<cols;c++){
for(var r:uint = 0;r<rows;r++){
cell[iterator] = createGamePiece();
Sprite(cell[iterator]).name = String(iterator);
Sprite(cell[iterator]).addEventListener(MouseEvent.CLICK, _handleGamePiece_CLICK);
Sprite(cell[iterator]).addEventListener(MouseEvent.MOUSE_OVER, _handleGamePiece_MOUSE_OVER);
Sprite(cell[iterator]).addEventListener(MouseEvent.MOUSE_OUT, _handleGamePiece_MOUSE_OUT);
cell[iterator].y = cell[iterator].height * r + (spacer*r);
cell[iterator].x = cell[iterator].width * c + (spacer*c);
GamePiece(cell[iterator]).positionX = cell[iterator].x;
GamePiece(cell[iterator]).positionY = cell[iterator].y;
GamePiece(cell[iterator]).positionRow = r;
GamePiece(cell[iterator]).positionCol = c;
target.addChild(cell[iterator]);
dictionary[String(iterator)] = cell[iterator]
iterator++
}
}
}
public function findRelativeMatches(targetSprite:Sprite) : void {
targetSprite.alpha = .5;
var rootPosition:Number = Number(targetSprite.name);
for ( var i:int = 0; i < relativePositions.length; i ++ ) {
var key:String = String(rootPosition + relativePositions[i].position);
// to do >> Not hardcoded to 'Pig'
if (findSprite(key) != null && GamePiece(targetSprite).color == GamePiece(findSprite(key)).color && GamePiece(findSprite(key)).found == false) {
var sprite:Sprite = findSprite(key);
sprite.alpha = .5;
GamePiece(sprite).found = true;
matches.push(sprite);
findRelativeMatches(sprite);
};
};
targetSprite.addEventListener(MouseEvent.MOUSE_OUT, function() : void {
if ( matches.length != 0 ) {
for ( var j:int = 0 ; j < matches.length ; j++ ) {
Sprite(matches[j]).alpha = 1;
GamePiece(matches[j]).found = false;
}
matches.splice(0);
}
});
}
public function findSprite(key:String) : Sprite {
var sprite:Sprite;
dictionary[key] != undefined ? sprite = dictionary[key] : null;
return sprite;
}
protected function _handleGamePiece_CLICK(event:MouseEvent):void
{
for ( var j:int = 0 ; j < matches.length ; j++ ) {
var sprite:Sprite = matches[j];
view.removeChild(matches[j]);
}
matches.splice(0);
}
public function createGamePiece() : Sprite {
var gamePiece:GamePiece = new GamePiece();
return gamePiece;
}
You want to collapse your grid downwards, right? The common algorithm is going from the bottom of every row upwards, having one index of the first empty space found, and the other for the first occupied space above empty space, then exchange those values once found, iterating to the top. But you don't store the grid in any accessible form! You should create a grid object, say a vector of vectors of sprites, and assign values in it as you move pieces around. Like this:
var GRID:Vector.<Vector.<Sprite>>; // this should be allocated at createGrid
// populate GRID with your sprites once generated:
// put the following into your inner loop in CreateGrid:
GRID[r][c]=cell[iterator];
// and the following into your removal of matches[] sprites:
GRID[GamePiece(sprite).positionRow][GamePiece(sprite).positionCol]=null; // release link from GRID
// now to move grid objects:
function DropAll():void {
var i:int;
var j:int;
for (i=GRID.length-1;i>=0;i--) {
var lastEmpty:int=-1;
for (j=GRID[i].length-1;j>=0;j--) {
if (GRID[i][j]) {
if (lastEmpty>0) {
GRID[i][lastEmpty--]=GRID[i][j];
// relocate your sprite properly here
GRID[i][j]=null;
} // else we're still at full part of grid, continue
} else if (lastEmpty<0) lastEmpty=j;
}
}
}
To properly instantiate GRID you need to allocate vectors of desired length that are filled with "null" values. Also, "GRID" itself is a Vector, and needs to be instantiated too.
GRID=new Vector.<Vector.<Sprite>>();
for (i=0;i<rows;i++) {
var a:Vector.<Sprite>=new Vector.<Sprite>(cols);
GRID.push(a);
}
After you do this, you fill the GRID by directly assigning links in it, like GRID[r][c]=gameObject;
This is actually what I wanted. A way to collapse WITHOUT iterating over the entire board. This way I JUST loop through the items that have been removed.
protected function _handleGamePiece_CLICK(event:MouseEvent):void
{
for ( var j:int = 0 ; j < matches.length ; j++ ) {
var oldSprite:Sprite = matches[j];
moveAllPiecesDown(oldSprite);
view.removeChild(oldSprite);
oldSprite = null;
}
matches.splice(0);
}
private function moveAllPiecesDown(oldSprite:Sprite):void
{
var piecesAbove:int = GamePiece(oldSprite).positionRow;
var index:int = int(oldSprite.name);
for( var i:int = 0; i < piecesAbove; i ++ ) {
var spriteAbove:Sprite = Sprite(view.getChildByName(String(index-(1+i))));
if(spriteAbove) {
spriteAbove.y = spriteAbove.y + spriteAbove.height + 1;
spriteAbove.name = String(Number(spriteAbove.name)+1);
GamePiece(spriteAbove).textField.text = spriteAbove.name;
delete dictionary[spriteAbove.name];
dictionary[spriteAbove.name] = spriteAbove;
}
}
}